00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 using System;
00013 using System.Collections.Generic;
00014 using System.Diagnostics;
00015 using System.EnterpriseServices.Internal;
00016 using System.Globalization;
00017 using System.IO;
00018 using System.Reflection;
00019 using System.Web.Services;
00020 using System.Xml;
00021 using Mcs.Epm.MicrosoftProject.mpFx.Client.Plugins.PsiExtensionGenerator.Properties;
00022 using Microsoft.Win32;
00023
00024 namespace Mcs.Epm.MicrosoftProject.mpFx.Client.Plugins.PsiExtensionGenerator
00025 {
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 internal class PsiExtensionGenerator
00072 {
00073 #region Static Methods
00074
00075
00076
00077
00078
00079
00080 internal static bool IsInstallDirectivePresent(string startupPath)
00081 {
00082 return File.Exists(GetInstalDirectivePath(startupPath));
00083 }
00084
00085
00086
00087
00088
00089
00090 private static string GetInstalDirectivePath(string startupPath)
00091 {
00092 return Path.Combine(startupPath, "setup.psieinstaller");
00093 }
00094
00095 #endregion
00096
00097 #region Delegates
00098
00099
00100
00101
00102
00103
00104 internal delegate void OnGenerationStatusChangedEventHandler(object sender, OnGenerationStatusChangedArgs args);
00105
00106 #endregion
00107
00108 #region Events
00109
00110
00111
00112
00113 internal event OnGenerationStatusChangedEventHandler OnGenerationStatusChanged;
00114
00115 #endregion
00116
00117 #region Instance Data
00118
00119 private readonly List<string> _ExclusionList = new List<string>(Settings.Default.ExclusionList.Split(','));
00120 private readonly List<string> _Output = new List<string>();
00121 private readonly List<string> _TempFiles = new List<string>();
00122
00123 private readonly bool _ResetIis;
00124 private readonly bool _DeployToBinDirectory;
00125 private readonly bool _OpenInBrowser;
00126
00127 private string _SourceAssemblyPath;
00128 private string _OfficeWebServicesPath;
00129 private string _IsapiDirectory;
00130 private string _SharedServiceProvider;
00131
00132 private Assembly _SourceAssembly;
00133 private Type _PsiExtensionType;
00134
00135 private string _WebServiceName;
00136
00137 private string _WebServiceFilePath;
00138 private string _DiscoFile;
00139 private string _WsdlFile;
00140
00141 private bool _IsError;
00142 private string _BinDirectory;
00143
00144 #endregion
00145
00146 #region Constructors
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 internal PsiExtensionGenerator(string sharedServiceProvider,
00158 string sourceAssemblyPath,
00159 string webServiceName,
00160 bool resetIis,
00161 bool openInBrowser,
00162 bool deployToBinDirectory)
00163 {
00164 DiscoveryOfficeWebServicesDirectory();
00165 DiscoverIsapiDirectory();
00166
00167 VerifyWebServiceName(webServiceName);
00168 VerifyAssemblyPath(sourceAssemblyPath);
00169
00170 VerifySharedServiceProviderUrl(sharedServiceProvider);
00171
00172 _DeployToBinDirectory = deployToBinDirectory;
00173 _ResetIis = resetIis;
00174 _OpenInBrowser = openInBrowser;
00175
00176 }
00177
00178
00179
00180
00181 internal PsiExtensionGenerator() {}
00182
00183 #endregion
00184
00185 #region internal Methods
00186
00187
00188
00189
00190 internal void Generate()
00191 {
00192 try
00193 {
00194
00195 _Output.Clear();
00196
00197 SetPsiExtensionType();
00198
00199 PrepareTargetPath();
00200
00201 WriteWebServiceFileContents();
00202
00203 MoveToVirtualDirectory();
00204
00205 if (_DeployToBinDirectory)
00206 {
00207 PublishToBinDirectory();
00208 }
00209 else
00210 {
00211 PublishToGac();
00212 }
00213
00214 UpdateWebConfig();
00215
00216 GenerateDiscoFiles();
00217
00218 MoveDiscoFiles();
00219
00220 FixUpDiscoFiles();
00221
00222 AddDepencencies();
00223
00224 if (_ResetIis)
00225 {
00226 ResetIis();
00227 }
00228
00229 if (_OpenInBrowser)
00230 {
00231 OpenInBrowser();
00232 }
00233
00234 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIComplete));
00235 }
00236 catch(Exception exception)
00237 {
00238 _IsError = true;
00239 throw new PsiGeneratorException(exception.Message, exception);
00240 }
00241 finally
00242 {
00243 CleanUp();
00244 }
00245 }
00246
00247 #endregion
00248
00249 #region Private Methods
00250
00251 #region Main Generation Methods
00252
00253
00254
00255
00256
00257
00258 private void SetPsiExtensionType()
00259 {
00260 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UILoadingAssembly));
00261
00262 Publish publish = new Publish();
00263
00264
00265
00266
00267
00268 publish.GacRemove(_SourceAssemblyPath);
00269
00270 _SourceAssembly = Assembly.LoadFile(_SourceAssemblyPath);
00271
00272 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UILoadingTypeInformation));
00273
00274 Type[] types = _SourceAssembly.GetTypes();
00275
00276
00277
00278 foreach (Type type in types)
00279 {
00280 WebServiceAttribute[] attributes = type.GetCustomAttributes(typeof(WebServiceAttribute), false) as WebServiceAttribute[];
00281
00282 if (attributes != null && attributes.Length > 0)
00283 {
00284 foreach (WebServiceAttribute attribute in attributes)
00285 {
00286 if (attribute.Namespace.StartsWith(Settings.Default.DefaultRootNameSpace, StringComparison.CurrentCultureIgnoreCase))
00287 {
00288 byte[] publicKey = _SourceAssembly.GetName().GetPublicKey();
00289
00290
00291 if (publicKey.Length == 0)
00292 {
00293 throw new PsiGeneratorException(Resources.AssemblyMustBeSigned);
00294 }
00295
00296 _PsiExtensionType = type;
00297
00298 return;
00299 }
00300 }
00301 }
00302 }
00303
00304 if (_PsiExtensionType == null)
00305 {
00306 throw new PsiGeneratorException(string.Format(CultureInfo.CurrentCulture,Resources.PsiWebServiceNotFound,
00307 Settings.Default.DefaultRootNameSpace));
00308 }
00309 }
00310
00311
00312
00313
00314
00315 private void PrepareTargetPath()
00316 {
00317 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIPrepTargetPath));
00318
00319 string targetPath = Path.Combine(Path.GetDirectoryName(_SourceAssemblyPath), _WebServiceName);
00320
00321 if (!Path.HasExtension(targetPath) || !Path.GetExtension(targetPath).Equals("asmx"))
00322 {
00323 targetPath = Path.ChangeExtension(targetPath, "asmx");
00324 }
00325
00326 if (File.Exists(targetPath))
00327 {
00328 File.Delete(targetPath);
00329 }
00330
00331 _WebServiceFilePath = targetPath;
00332 }
00333
00334
00335
00336
00337
00338 private void WriteWebServiceFileContents()
00339 {
00340 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIWriteWebServiceFile));
00341
00342 using (StreamWriter writer = File.CreateText(_WebServiceFilePath))
00343 {
00344 writer.AutoFlush = true;
00345 writer.WriteLine(string.Format(CultureInfo.CurrentCulture,Resources.AsmxContents, Settings.Default.WebServiceLanguage,
00346 _PsiExtensionType.AssemblyQualifiedName));
00347 }
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 private void MoveToVirtualDirectory()
00361 {
00362 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIMoveToVirtualDirectory));
00363
00364 string copyTarget = Path.Combine(_OfficeWebServicesPath, Path.GetFileName(_WebServiceFilePath));
00365
00366 if (File.Exists(copyTarget))
00367 {
00368 File.Delete(copyTarget);
00369 }
00370
00371 File.Move(_WebServiceFilePath, copyTarget);
00372
00373 _WebServiceFilePath = copyTarget;
00374 }
00375
00376
00377
00378
00379 private void GenerateDiscoFiles()
00380 {
00381 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIGeneratingDiscoFiles));
00382
00383 Environment.CurrentDirectory = Path.GetDirectoryName(_SourceAssemblyPath);
00384
00385 string discoPath = GetDiscoExePath();
00386
00387 string webServiceUrl = GetPsiWebServiceUrl();
00388
00389 CreateProcess(discoPath, webServiceUrl);
00390
00391 bool terminate = false;
00392
00393
00394
00395 List<string> htmlOutput = new List<string>();
00396 bool inhtmlOutput = false;
00397
00398 foreach (string outputMessage in _Output)
00399 {
00400 if (outputMessage.Contains("ERROR"))
00401 {
00402 terminate = true;
00403 }
00404 if (outputMessage.StartsWith("<html>", StringComparison.CurrentCultureIgnoreCase))
00405 {
00406 inhtmlOutput = true;
00407 }
00408 else if (outputMessage.StartsWith("</html>", StringComparison.CurrentCultureIgnoreCase))
00409 {
00410 htmlOutput.Add(outputMessage);
00411 inhtmlOutput = false;
00412 }
00413 else
00414 {
00415 if (!inhtmlOutput)
00416 {
00417 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(outputMessage));
00418 }
00419 }
00420
00421 if (inhtmlOutput)
00422 {
00423 htmlOutput.Add(outputMessage);
00424 }
00425 }
00426
00427 if (htmlOutput.Count > 0)
00428 {
00429
00430
00431 string tempFile = Path.GetTempFileName();
00432
00433 if (File.Exists(tempFile))
00434 {
00435 File.Delete(tempFile);
00436 }
00437
00438 tempFile = Path.ChangeExtension(tempFile, "htm");
00439
00440 File.WriteAllLines(tempFile, htmlOutput.ToArray());
00441
00442 Process.Start(tempFile);
00443
00444 _TempFiles.Add(tempFile);
00445 }
00446
00447 string discoResults = Path.Combine(Path.GetDirectoryName(_SourceAssemblyPath), "results.discomap");
00448
00449 if (File.Exists(discoResults))
00450 {
00451 _TempFiles.Add(discoResults);
00452 }
00453
00454 if (terminate)
00455 {
00456 throw new PsiGeneratorException(Resources.ErrorDiscoGenerationFailed);
00457 }
00458
00459 }
00460
00461
00462
00463
00464 private void MoveDiscoFiles()
00465 {
00466 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIMovingDiscoFiles));
00467
00468 string outputPath = Path.GetDirectoryName(_SourceAssemblyPath);
00469
00470 _WsdlFile = MoveDiscoveryFile(outputPath, "wsdl", Resources.ErrorMoveWsdl);
00471
00472 _DiscoFile = MoveDiscoveryFile(outputPath, "disco", Resources.ErrorMoveDisco);
00473 }
00474
00475
00476
00477
00478 private void FixUpDiscoFiles()
00479 {
00480 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIFixupDiscoFiles));
00481
00482 List<string> file = new List<string>();
00483
00484 file.AddRange(File.ReadAllLines(_DiscoFile));
00485 FixUpHeader(file);
00486
00487 SetElementAttributeValue(file, "contractRef", "ref", Resources.refContents);
00488 SetElementAttributeValue(file, "contractRef", "docRef", Resources.docRefContents);
00489 SetElementAttributeValue(file, "soap", "address", Resources.addressContents);
00490
00491 File.WriteAllLines(_DiscoFile, file.ToArray());
00492
00493 file.Clear();
00494
00495 file.AddRange(File.ReadAllLines(_WsdlFile));
00496 FixUpHeader(file);
00497
00498 SetElementAttributeValue(file, "soap:address", "location", Resources.soapAddressContents);
00499 SetElementAttributeValue(file, "soap12:address", "location", Resources.soapAddressContents);
00500
00501 File.WriteAllLines(_WsdlFile, file.ToArray());
00502 }
00503
00504
00505
00506
00507 private void PublishToGac()
00508 {
00509 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIPublishingToGac));
00510
00511 Publish publish = new Publish();
00512
00513 if (_SourceAssembly.GlobalAssemblyCache)
00514 {
00515 if (_SourceAssembly.Location == null)
00516 {
00517 throw new PsiGeneratorException(Resources.ErrorAssemblyLocation);
00518 }
00519
00520 publish.GacRemove(_SourceAssembly.Location);
00521 }
00522
00523 publish.GacInstall(_SourceAssemblyPath);
00524 }
00525
00526
00527
00528
00529 private void UpdateWebConfig()
00530 {
00531 string webConfigFilePath = Path.GetDirectoryName(_WebServiceFilePath);
00532
00533 webConfigFilePath = Path.Combine(webConfigFilePath, "web.config");
00534
00535 if (!File.Exists(webConfigFilePath))
00536 {
00537 throw new PsiGeneratorException(Resources.ErrorWebConfigNotFound);
00538 }
00539
00540 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(string.Format(CultureInfo.CurrentCulture, Resources.UIAddingToWebConfig, webConfigFilePath)));
00541
00542 XmlDocument configXml = new XmlDocument();
00543 configXml.Load(webConfigFilePath);
00544
00545 XmlNode assembliesNode = configXml.SelectSingleNode("/configuration/system.web/compilation/assemblies");
00546
00547 bool exitSearch = false;
00548
00549 for (int j = 0; j < assembliesNode.ChildNodes.Count; j++)
00550 {
00551 for (int i = 0; i < assembliesNode.ChildNodes[j].Attributes.Count; i++)
00552 {
00553 if (assembliesNode.ChildNodes[j].Attributes[i].Value.Equals(_PsiExtensionType.Assembly.FullName))
00554 {
00555
00556 assembliesNode.RemoveChild(assembliesNode.ChildNodes[j]);
00557 exitSearch = true;
00558 break;
00559 }
00560 }
00561
00562 if (exitSearch)
00563 {
00564 break;
00565 }
00566 }
00567
00568 XmlNode assemblyNode = configXml.CreateElement("add");
00569
00570 XmlAttribute assemblyAttribute = configXml.CreateAttribute("assembly");
00571
00572 assemblyNode.Attributes.Append(assemblyAttribute);
00573
00574 assemblyAttribute.Value = _PsiExtensionType.Assembly.FullName;
00575
00576 assembliesNode.AppendChild(assemblyNode);
00577
00578 configXml.Save(webConfigFilePath);
00579 }
00580
00581
00582
00583
00584 private void ResetIis()
00585 {
00586 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIResetIis));
00587
00588 _Output.Clear();
00589
00590 Process process = new Process
00591 {
00592 StartInfo =
00593 {
00594 FileName = "IISRESET",
00595 CreateNoWindow = true,
00596 RedirectStandardError = true,
00597 RedirectStandardOutput = true,
00598 UseShellExecute = false
00599 },
00600 EnableRaisingEvents = true
00601 };
00602
00603 process.OutputDataReceived += process_OutputDataReceived;
00604 process.ErrorDataReceived += process_ErrorDataReceived;
00605
00606 process.Start();
00607
00608 process.BeginOutputReadLine();
00609 process.BeginErrorReadLine();
00610
00611 process.WaitForExit();
00612
00613 foreach (string outputMessage in _Output)
00614 {
00615 if (outputMessage.StartsWith("-", StringComparison.CurrentCultureIgnoreCase))
00616 {
00617 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(outputMessage));
00618 }
00619 else
00620 {
00621 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(string.Format(CultureInfo.CurrentCulture,"\t{0}", outputMessage)));
00622 }
00623 }
00624 }
00625
00626
00627
00628
00629 private void OpenInBrowser()
00630 {
00631 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(Resources.UIOpenInBrowser));
00632 string url = GetPsiWebServiceUrl();
00633
00634 Process.Start(url);
00635 }
00636
00637
00638
00639
00640 private void CleanUp()
00641 {
00642 if (_IsError)
00643 {
00644 if (_DeployToBinDirectory && !string.IsNullOrEmpty(_BinDirectory))
00645 {
00646 string targetPath = Path.Combine(_BinDirectory, Path.GetFileName(_SourceAssemblyPath));
00647
00648 DeleteFile(targetPath);
00649 }
00650 else
00651 {
00652 UninstallFromGac();
00653 }
00654 }
00655
00656 foreach (string file in _TempFiles)
00657 {
00658 if (File.Exists(file))
00659 {
00660 try
00661 {
00662 File.Delete(file);
00663 }
00664 catch
00665 { }
00666 }
00667 }
00668 }
00669
00670 #endregion
00671
00672 #region Wrappers
00673
00674 private void DoOnGenerationStatusChanged(OnGenerationStatusChangedArgs args)
00675 {
00676 if (OnGenerationStatusChanged != null)
00677 {
00678 OnGenerationStatusChanged(this, args);
00679 }
00680 }
00681
00682 private void CreateProcess(string fileName, string arguements)
00683 {
00684 Process process = new Process
00685 {
00686 StartInfo =
00687 {
00688 FileName = fileName,
00689 CreateNoWindow = true,
00690 Arguments = arguements,
00691 RedirectStandardError = true,
00692 RedirectStandardOutput = true,
00693 UseShellExecute = false
00694 },
00695 EnableRaisingEvents = true
00696 };
00697
00698 process.OutputDataReceived += process_OutputDataReceived;
00699 process.ErrorDataReceived += process_ErrorDataReceived;
00700
00701 process.Start();
00702
00703 process.BeginOutputReadLine();
00704 process.BeginErrorReadLine();
00705
00706 process.WaitForExit();
00707 }
00708
00709 private static void DeleteFile(string tempFile)
00710 {
00711 if (File.Exists(tempFile))
00712 {
00713 File.Delete(tempFile);
00714 }
00715 }
00716
00717
00718 private void ReportFeedback(DataReceivedEventArgs e)
00719 {
00720 if (!string.IsNullOrEmpty(e.Data))
00721 {
00722 _Output.Add(e.Data);
00723 }
00724 }
00725
00726 #endregion
00727
00728 #region Publishing methods
00729
00730
00731
00732
00733 private void PublishToBinDirectory()
00734 {
00735 DirectoryInfo parentDirectory = Directory.GetParent(_OfficeWebServicesPath);
00736
00737 if (parentDirectory == null)
00738 {
00739 throw new DirectoryNotFoundException(_OfficeWebServicesPath);
00740 }
00741
00742 _BinDirectory = Path.Combine(parentDirectory.FullName, "Bin");
00743
00744 if (!Directory.Exists(_BinDirectory))
00745 {
00746 Directory.CreateDirectory(_BinDirectory);
00747 }
00748
00749 string targetPath = Path.Combine(_BinDirectory, Path.GetFileName(_SourceAssemblyPath));
00750 DeleteFile(targetPath);
00751
00752 File.Copy(_SourceAssemblyPath, targetPath);
00753
00754 }
00755
00756
00757
00758
00759 private void UninstallFromGac()
00760 {
00761 Publish publish = new Publish();
00762
00763 if (_SourceAssembly.GlobalAssemblyCache)
00764 {
00765 if (_SourceAssembly.Location == null)
00766 {
00767 throw new PsiGeneratorException(Resources.ErrorAssemblyLocation);
00768 }
00769
00770 publish.GacRemove(_SourceAssembly.Location);
00771 }
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790 private void AddDepencencies()
00791 {
00792 AssemblyName[] referencedAssemblies = _SourceAssembly.GetReferencedAssemblies();
00793
00794 string[] files = Directory.GetFiles(Path.GetDirectoryName(_SourceAssemblyPath), "*.dll");
00795
00796 Dictionary<AssemblyName, Assembly> assemblies = new Dictionary<AssemblyName, Assembly>();
00797
00798 foreach (string file in files)
00799 {
00800 try
00801 {
00802 AssemblyName name = AssemblyName.GetAssemblyName(file);
00803
00804 assemblies.Add(name, Assembly.LoadFile(file));
00805 }
00806 catch (BadImageFormatException) { }
00807 }
00808
00809 foreach (AssemblyName assemblyName in referencedAssemblies)
00810 {
00811 if (!IsInExclusionList(assemblyName))
00812 {
00813 foreach (KeyValuePair<AssemblyName, Assembly> pair in assemblies)
00814 {
00815 if (pair.Value.FullName == assemblyName.FullName)
00816 {
00817 DoOnGenerationStatusChanged(new OnGenerationStatusChangedArgs(string.Format(CultureInfo.CurrentCulture, Resources.UIAddDependency, assemblyName.FullName)));
00818
00819 Assembly assembly = assemblies[pair.Key];
00820
00821 if (assembly.Location == null)
00822 {
00823 throw new PsiGeneratorException(string.Format(CultureInfo.CurrentCulture, Resources.ErrorDependentAssemblyLocation, assembly.FullName));
00824 }
00825
00826 if (_DeployToBinDirectory)
00827 {
00828 string fileName = Path.GetFileName(assembly.Location);
00829
00830 fileName = Path.Combine(_BinDirectory, fileName);
00831
00832 if (File.Exists(fileName))
00833 {
00834 File.Delete(fileName);
00835 }
00836
00837 File.Copy(assembly.Location, fileName);
00838 }
00839 else
00840 {
00841 Publish publish = new Publish();
00842 publish.GacRemove(assembly.Location);
00843 publish.GacInstall(assembly.Location);
00844 }
00845 break;
00846 }
00847 }
00848 }
00849 }
00850 }
00851
00852
00853
00854
00855
00856
00857
00858 private bool IsInExclusionList(AssemblyName assemblyName)
00859 {
00860 string assemblyFullName = assemblyName.FullName;
00861
00862 if (assemblyFullName.Equals(_SourceAssembly.FullName))
00863 {
00864 return true;
00865 }
00866
00867 foreach (string excludedItem in _ExclusionList)
00868 {
00869 if (assemblyFullName.StartsWith(excludedItem, StringComparison.CurrentCultureIgnoreCase))
00870 {
00871 return true;
00872 }
00873 }
00874
00875 return false;
00876 }
00877
00878 #endregion
00879
00880 #region Path Creation & Discovery Methods
00881
00882
00883
00884
00885 private void DiscoverIsapiDirectory()
00886 {
00887 using (RegistryKey officeServerKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\SharePoint"))
00888 {
00889 if (officeServerKey != null)
00890 {
00891 object keyValue = officeServerKey.GetValue(string.Empty);
00892
00893 if (keyValue != null)
00894 {
00895 string isapiDirectory = keyValue.ToString();
00896
00897 isapiDirectory = Path.Combine(isapiDirectory, "PSI");
00898
00899 if (Directory.Exists(isapiDirectory))
00900 {
00901 _IsapiDirectory = isapiDirectory;
00902 return;
00903 }
00904 }
00905 }
00906 }
00907
00908 throw new PsiGeneratorException("ISAPI directory not found.");
00909 }
00910
00911
00912
00913
00914 private void DiscoveryOfficeWebServicesDirectory()
00915 {
00916 using (RegistryKey officeServerKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Office Server\12.0"))
00917 {
00918 if (officeServerKey != null)
00919 {
00920 object keyValue = officeServerKey.GetValue("BinPath");
00921
00922 if (keyValue != null)
00923 {
00924 _OfficeWebServicesPath = keyValue.ToString();
00925
00926 if (_OfficeWebServicesPath.EndsWith("\\", StringComparison.CurrentCultureIgnoreCase))
00927
00928 {
00929
00930 _OfficeWebServicesPath = _OfficeWebServicesPath.Substring(0, _OfficeWebServicesPath.Length - 1);
00931 }
00932 }
00933 }
00934 }
00935
00936 DirectoryInfo parentDirectory = Directory.GetParent(_OfficeWebServicesPath);
00937
00938 if (parentDirectory != null)
00939 {
00940 _OfficeWebServicesPath = parentDirectory.FullName;
00941
00942 _OfficeWebServicesPath = Path.Combine(_OfficeWebServicesPath, "WebServices\\Shared\\PSI");
00943
00944 if (Directory.Exists(_OfficeWebServicesPath))
00945 {
00946 return;
00947 }
00948 }
00949
00950 throw new PsiGeneratorException(Resources.ErrorMustRunOnProjectServer);
00951 }
00952
00953
00954
00955
00956
00957 private string GetPsiWebServiceUrl()
00958 {
00959 return string.Format(CultureInfo.CurrentCulture, "{0}PSI/{1}", _SharedServiceProvider, Path.GetFileName(_WebServiceFilePath));
00960 }
00961
00962
00963
00964
00965
00966 private static string GetDiscoExePath()
00967 {
00968 string discoPath = Assembly.GetExecutingAssembly().Location;
00969
00970 discoPath = Path.GetDirectoryName(discoPath);
00971
00972 discoPath = Path.Combine(discoPath, "disco.exe");
00973
00974 if (!File.Exists(discoPath))
00975 {
00976 throw new FileNotFoundException(string.Format(CultureInfo.CurrentCulture, "File not found: {0}", discoPath));
00977 }
00978
00979 return discoPath;
00980 }
00981
00982 #endregion
00983
00984 #region Verification Methods
00985
00986
00987
00988
00989
00990 private void VerifyAssemblyPath(string sourceAssemblyPath)
00991 {
00992 if (string.IsNullOrEmpty(sourceAssemblyPath))
00993 {
00994 throw new ArgumentException(Resources.ErrorInvalidSourcePath);
00995 }
00996
00997 if (!File.Exists(sourceAssemblyPath))
00998 {
00999 throw new FileNotFoundException(_SourceAssemblyPath);
01000 }
01001
01002 _SourceAssemblyPath = sourceAssemblyPath;
01003 }
01004
01005
01006
01007
01008
01009 private void VerifyWebServiceName(string webServiceName)
01010 {
01011 if (string.IsNullOrEmpty(webServiceName))
01012 {
01013 throw new ArgumentException(Resources.ErrorInvalidWebServiceName);
01014 }
01015 _WebServiceName = webServiceName;
01016 }
01017
01018
01019
01020
01021
01022 private void VerifySharedServiceProviderUrl(string sharedServiceProvider)
01023 {
01024 Uri testUri;
01025
01026 _SharedServiceProvider = sharedServiceProvider;
01027
01028 if (!Uri.TryCreate(_SharedServiceProvider, UriKind.Absolute, out testUri))
01029 {
01030 throw new UriFormatException(Resources.ErrorInvalidShareServiceProviderUrl);
01031 }
01032
01033 if (!_SharedServiceProvider.EndsWith("/", StringComparison.CurrentCultureIgnoreCase))
01034 {
01035 _SharedServiceProvider = string.Format(CultureInfo.CurrentCulture,"{0}/", _SharedServiceProvider);
01036 }
01037 }
01038
01039 #endregion
01040
01041 #region Discovery File Manipulation Methods
01042
01043
01044
01045
01046
01047 private static void FixUpHeader(IList<string> file)
01048 {
01049 file.RemoveAt(0);
01050 file.Insert(0, Resources.importSharePointObjectModelContents);
01051 }
01052
01053
01054
01055
01056
01057
01058
01059
01060 private static void SetElementAttributeValue(IList<string> file, string elementName, string attributeName, string value)
01061 {
01062 int count = 0;
01063
01064 if (!elementName.StartsWith("<", StringComparison.CurrentCultureIgnoreCase))
01065 {
01066 elementName = string.Format(CultureInfo.CurrentCulture,"<{0}", elementName);
01067 }
01068
01069 for (int i = 0; i < file.Count; i++)
01070 {
01071 string line = file[i];
01072 string trimmedLine = line.Trim();
01073
01074 if (trimmedLine.StartsWith(elementName, StringComparison.CurrentCultureIgnoreCase))
01075 {
01076 string attributeWithEquals = string.Format(CultureInfo.CurrentCulture,"{0}=", attributeName);
01077
01078 int attributeStart = trimmedLine.IndexOf(attributeWithEquals, StringComparison.CurrentCultureIgnoreCase);
01079
01080 if (attributeStart != -1)
01081 {
01082 string attributeAndValue = trimmedLine.Substring(attributeStart);
01083
01084 int openingQuotes = attributeAndValue.IndexOf("\"", StringComparison.CurrentCultureIgnoreCase);
01085 int closingQuotes = attributeAndValue.IndexOf("\"", openingQuotes + 1, StringComparison.CurrentCultureIgnoreCase);
01086
01087 attributeAndValue = attributeAndValue.Substring(0, closingQuotes);
01088
01089 file[i] = file[i].Replace(attributeAndValue, attributeName + "=\"" + value);
01090
01091 count++;
01092 }
01093 }
01094 }
01095
01096 if (count == 0)
01097 {
01098 throw new PsiGeneratorException(string.Format(CultureInfo.CurrentCulture,Resources.ErrorXmlNotFound, elementName, attributeName));
01099 }
01100 }
01101
01102
01103
01104
01105
01106
01107
01108
01109 private string MoveDiscoveryFile(string outputPath, string suffix, string errorMessage)
01110 {
01111 string fileName = Path.GetFileName(_WebServiceFilePath);
01112
01113 string filePath = Path.Combine(outputPath, Path.ChangeExtension(fileName, suffix));
01114
01115 if (!File.Exists(filePath))
01116 {
01117 throw new PsiGeneratorException(errorMessage);
01118 }
01119
01120 string targetFile = Path.GetFileNameWithoutExtension(fileName);
01121
01122 targetFile = string.Format(CultureInfo.CurrentCulture, "{1}{0}.aspx", suffix, targetFile);
01123 targetFile = Path.Combine(_IsapiDirectory, targetFile);
01124
01125 DeleteFile(targetFile);
01126
01127 File.Move(filePath, targetFile);
01128
01129 return targetFile;
01130 }
01131
01132 #endregion
01133
01134 #region Miscellanous
01135
01136 #endregion
01137
01138 #endregion
01139
01140 #region Event Handlers
01141
01142 private void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
01143 {
01144 ReportFeedback(e);
01145 }
01146
01147 private void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
01148 {
01149 ReportFeedback(e);
01150 }
01151
01152 #endregion
01153 }
01154 }