Index: Tests/common.eagle ================================================================== --- Tests/common.eagle +++ Tests/common.eagle @@ -300,16 +300,23 @@ proc tryLoadAssembly { fileName } { set fileName [getBinaryFileName $fileName] if {[catch {set assembly \ - [object load -loadtype File $fileName]}] == 0} then { + [object load -loadtype File -alias $fileName]}] == 0} then { # # NOTE: Now, add the necessary test constraint. # addConstraint [file rootname [file tail $fileName]] + # + # NOTE: Grab the image runtime version from the assembly because + # several tests rely on it having a certain value. + # + addConstraint [appendArgs [file tail $fileName] _ \ + [$assembly ImageRuntimeVersion]] + # # NOTE: Return the full path of the loaded file. # return $fileName } @@ -705,10 +712,16 @@ # # NOTE: Report the resource usage prior to running any tests. # reportSQLiteResources $::test_channel + + # + # NOTE: Show the active test constraints. + # + tputs $::test_channel [appendArgs "---- constraints: " \ + [formatList [lsort [getConstraints]]] \n] } } proc runSQLiteTestEpilogue {} { # Index: Tests/installer.eagle ================================================================== --- Tests/installer.eagle +++ Tests/installer.eagle @@ -88,13 +88,12 @@ [subst -nobackslashes [readFile $testInstallVs2008LogFile]]] : $error}] } -cleanup { catch {file delete $fileName} unset -nocomplain code output error fileName -} -constraints \ -{eagle visualStudio2008 file_Installer.exe file_Installer_Test_Vs2008.log} \ --result {0 True}} +} -constraints {eagle visualStudio2008 System.Data.SQLite.dll_v2.0.50727\ +file_Installer.exe file_Installer_Test_Vs2008.log} -result {0 True}} ############################################################################### runTest {test installer-1.2 {uninstaller tool / Visual Studio 2008} -setup { set fileName [file join [getTemporaryPath] \ @@ -120,13 +119,12 @@ [subst -nobackslashes [readFile $testUninstallVs2008LogFile]]] : $error}] } -cleanup { catch {file delete $fileName} unset -nocomplain code output error fileName -} -constraints \ -{eagle visualStudio2008 file_Installer.exe file_Uninstaller_Test_Vs2008.log} \ --result {0 True}} +} -constraints {eagle visualStudio2008 System.Data.SQLite.dll_v2.0.50727\ +file_Installer.exe file_Uninstaller_Test_Vs2008.log} -result {0 True}} ############################################################################### runTest {test installer-1.3 {installer tool / Visual Studio 2010} -setup { set fileName [file join [getTemporaryPath] \ @@ -152,13 +150,12 @@ [subst -nobackslashes [readFile $testInstallVs2010LogFile]]] : $error}] } -cleanup { catch {file delete $fileName} unset -nocomplain code output error fileName -} -constraints \ -{eagle visualStudio2010 file_Installer.exe file_Installer_Test_Vs2010.log} \ --result {0 True}} +} -constraints {eagle visualStudio2010 System.Data.SQLite.dll_v4.0.30319\ +file_Installer.exe file_Installer_Test_Vs2010.log} -result {0 True}} ############################################################################### runTest {test installer-1.4 {uninstaller tool / Visual Studio 2010} -setup { set fileName [file join [getTemporaryPath] \ @@ -184,13 +181,12 @@ [subst -nobackslashes [readFile $testUninstallVs2010LogFile]]] : $error}] } -cleanup { catch {file delete $fileName} unset -nocomplain code output error fileName -} -constraints \ -{eagle visualStudio2010 file_Installer.exe file_Uninstaller_Test_Vs2010.log} \ --result {0 True}} +} -constraints {eagle visualStudio2010 System.Data.SQLite.dll_v4.0.30319\ +file_Installer.exe file_Uninstaller_Test_Vs2010.log} -result {0 True}} ############################################################################### unset -nocomplain testUninstallVs2010LogFile testUninstallVs2008LogFile \ testInstallVs2010LogFile testInstallVs2008LogFile installerExeFile \ Index: tools/install/Installer.cs ================================================================== --- tools/install/Installer.cs +++ tools/install/Installer.cs @@ -56,14 +56,11 @@ /////////////////////////////////////////////////////////////////////////// internal delegate bool VisualStudioRegistryCallback( RegistryKey rootKey, Version vsVersion, - Guid packageId, - Guid serviceId, - Guid dataSourceId, - Guid dataProviderId, + Installer.Package package, object clientData, bool whatIf, bool verbose, ref string error ); @@ -1280,10 +1277,83 @@ } #endregion /////////////////////////////////////////////////////////////////////// + #region VersionListMap Class + private sealed class VersionListMap : Dictionary + { + public VersionListMap() + { + // do nothing. + } + } + #endregion + + /////////////////////////////////////////////////////////////////////// + + #region Package Class + internal sealed class Package + { + #region Public Constructors + public Package() + { + // do nothing. + } + #endregion + + /////////////////////////////////////////////////////////////////// + + #region Public Properties + private Guid packageId; + public Guid PackageId + { + get { return packageId; } + set { packageId = value; } + } + + /////////////////////////////////////////////////////////////////// + + private Guid serviceId; + public Guid ServiceId + { + get { return serviceId; } + set { serviceId = value; } + } + + /////////////////////////////////////////////////////////////////// + + private Guid dataSourceId; + public Guid DataSourceId + { + get { return dataSourceId; } + set { dataSourceId = value; } + } + + /////////////////////////////////////////////////////////////////// + + private Guid dataProviderId; + public Guid DataProviderId + { + get { return dataProviderId; } + set { dataProviderId = value; } + } + + /////////////////////////////////////////////////////////////////// + + private Guid adoNetTechnologyId; + public Guid AdoNetTechnologyId + { + get { return adoNetTechnologyId; } + set { adoNetTechnologyId = value; } + } + #endregion + } + #endregion + + /////////////////////////////////////////////////////////////////////// + #region Configuration Class private sealed class Configuration { #region Private Constants private const char Switch = '-'; @@ -2062,10 +2132,15 @@ // NOTE: Show where we are running from and how we were // invoked. // string location = assembly.Location; + TraceOps.Trace( + TracePriority.Medium, traceCallback, String.Format( + "Running executable is: {0}", ForDisplay(location)), + traceCategory); + TraceOps.Trace( TracePriority.Medium, traceCallback, String.Format( "Original command line is: {0}", Environment.CommandLine), traceCategory); @@ -2114,10 +2189,115 @@ TracePriority.Highest, traceCallback, e, traceCategory); error = "Failed to process configuration."; } + + return false; + } + + /////////////////////////////////////////////////////////////////// + + public static bool CheckRuntimeVersion( + Configuration configuration, + bool strict, + ref string error + ) + { + try + { + if (configuration == null) + { + error = "Invalid configuration."; + return false; + } + + // + // NOTE: What version of the runtime was the core (primary) + // assembly compiled against (e.g. "v2.0.50727" or + // "v4.0.30319"). + // + string coreImageRuntimeVersion = GetImageRuntimeVersion( + configuration.coreFileName); + + // + // TODO: Restrict the configuration based on which image + // runtime versions (which more-or-less correspond + // to .NET Framework versions) are supported by the + // versions of Visual Studio that are installed. + // + if (String.IsNullOrEmpty(coreImageRuntimeVersion)) + { + error = "invalid core file image runtime version"; + return false; + } + else if (String.Equals( + coreImageRuntimeVersion, CLR2ImageRuntimeVersion, + StringComparison.InvariantCulture)) + { + // + // NOTE: For the CLR v2.0 runtime, make sure we disable + // any attempt to use it for things that require + // an assembly compiled for the CLR v4.0. It is + // uncertain if this is actually a problem in + // practice as the CLR v4.0 can load and use an + // assembly compiled with the CLR v2.0; however, + // since this project offers both configurations, + // we currently disallow this mismatch. + // + configuration.noNetFx40 = true; + configuration.noVs2010 = true; + + TraceOps.Trace( + TracePriority.Medium, traceCallback, String.Format( + "Assembly is compiled for the .NET Framework {0}, " + + "support for .NET Framework {1} is now disabled.", + CLR2ImageRuntimeVersion, CLR4ImageRuntimeVersion), + traceCategory); + } + else if (String.Equals( + coreImageRuntimeVersion, CLR4ImageRuntimeVersion, + StringComparison.InvariantCulture)) + { + // + // NOTE: For the CLR v4.0 runtime, make sure we disable + // any attempt to use it for things that require + // an assembly compiled for the CLR v2.0. + // + configuration.noNetFx20 = true; + configuration.noVs2008 = true; + + TraceOps.Trace( + TracePriority.Medium, traceCallback, String.Format( + "Assembly is compiled for the .NET Framework {0}, " + + "support for .NET Framework {1} is now disabled.", + ForDisplay(CLR4ImageRuntimeVersion), + ForDisplay(CLR2ImageRuntimeVersion)), + traceCategory); + } + else + { + error = String.Format( + "unsupported core file image runtime version " + + "{0}, must be {1} or {2}", + ForDisplay(coreImageRuntimeVersion), + ForDisplay(CLR2ImageRuntimeVersion), + ForDisplay(CLR4ImageRuntimeVersion)); + + return false; + } + + return true; + } + catch (Exception e) + { + TraceOps.Trace( + TracePriority.Highest, traceCallback, e, + traceCategory); + + error = "Failed to check image runtime version."; + } return false; } #endregion @@ -2431,10 +2611,114 @@ set { confirm = value; } } #endregion } #endregion + + /////////////////////////////////////////////////////////////////////// + + #region FrameworkList Class + private sealed class FrameworkList + { + #region Public Constructors + public FrameworkList() + { + // do nothing. + } + #endregion + + /////////////////////////////////////////////////////////////////// + + #region Public Methods + private RegistryKey rootKey; + public RegistryKey RootKey + { + get { return rootKey; } + set { rootKey = value; } + } + + /////////////////////////////////////////////////////////////////// + + private StringList names; + public StringList Names + { + get { return names; } + set { names = value; } + } + + /////////////////////////////////////////////////////////////////// + + private VersionMap versions; + public VersionMap Versions + { + get { return versions; } + set { versions = value; } + } + + /////////////////////////////////////////////////////////////////// + + private StringList platformNames; + public StringList PlatformNames + { + get { return platformNames; } + set { platformNames = value; } + } + #endregion + } + #endregion + + /////////////////////////////////////////////////////////////////////// + + #region VsList Class + private sealed class VsList + { + #region Public Constructors + public VsList() + { + // do nothing. + } + #endregion + + /////////////////////////////////////////////////////////////////// + + #region Public Properties + private RegistryKey rootKey; + public RegistryKey RootKey + { + get { return rootKey; } + set { rootKey = value; } + } + + /////////////////////////////////////////////////////////////////// + + private VersionList versions; + public VersionList Versions + { + get { return versions; } + set { versions = value; } + } + + /////////////////////////////////////////////////////////////////// + + private VersionListMap frameworkVersions; + public VersionListMap FrameworkVersions + { + get { return frameworkVersions; } + set { frameworkVersions = value; } + } + + /////////////////////////////////////////////////////////////////// + + private VersionList installedVersions; + public VersionList InstalledVersions + { + get { return installedVersions; } + set { installedVersions = value; } + } + #endregion + } + #endregion #endregion /////////////////////////////////////////////////////////////////////// #region Private Constant Data @@ -2445,10 +2729,15 @@ private const string ProjectName = "System.Data.SQLite"; private const string LegacyProjectName = "SQLite"; private const string InvariantName = "System.Data.SQLite"; private const string FactoryTypeName = "System.Data.SQLite.SQLiteFactory"; private const string Description = ".NET Framework Data Provider for SQLite"; + + /////////////////////////////////////////////////////////////////////// + + private const string CLR2ImageRuntimeVersion = "v2.0.50727"; + private const string CLR4ImageRuntimeVersion = "v4.0.30319"; /////////////////////////////////////////////////////////////////////// private const string NameAndValueFormat = "{0}: {1}"; private const string LogFileSuffix = ".log"; @@ -2481,34 +2770,17 @@ "configuration/system.data/DbProviderFactories/remove[@invariant=\"{0}\"]"; #endregion /////////////////////////////////////////////////////////////////////// - #region Private Data + #region Private Static Data private static Assembly thisAssembly = Assembly.GetExecutingAssembly(); private static string traceCategory = Path.GetFileName( thisAssembly.Location); private static TraceCallback traceCallback = AppTrace; - - /////////////////////////////////////////////////////////////////////// - - private static RegistryKey frameworkRootKey; - private static StringList frameworkNameList; - private static VersionMap frameworkVersionMap; - private static StringList platformNameList; - - /////////////////////////////////////////////////////////////////////// - - private static RegistryKey vsRootKey; - private static VersionList vsVersionList; - private static Guid? vsPackageId; - private static Guid? vsServiceId; - private static Guid? vsDataSourcesId; - private static Guid? vsDataProviderId; - private static Guid? vsAdoNetTechnologyId; #endregion /////////////////////////////////////////////////////////////////////// #region Trace Handling @@ -2577,10 +2849,32 @@ #endregion /////////////////////////////////////////////////////////////////////// #region .NET Framework Handling + private static string GetImageRuntimeVersion( + string fileName + ) + { + try + { + Assembly assembly = + Assembly.ReflectionOnlyLoadFrom(fileName); /* throw */ + + if (assembly != null) + return assembly.ImageRuntimeVersion; + } + catch + { + // do nothing. + } + + return null; + } + + /////////////////////////////////////////////////////////////////////// + private static string GetFrameworkDirectory( RegistryKey rootKey, Version frameworkVersion, bool whatIf, bool verbose @@ -2724,68 +3018,81 @@ #endregion /////////////////////////////////////////////////////////////////////// #region Per-Framework/Platform Handling - private static void InitializeAllFrameworks( - Configuration configuration - ) - { - if (frameworkRootKey == null) - frameworkRootKey = Registry.LocalMachine; - - if (frameworkNameList == null) - { - frameworkNameList = new StringList(); - - if ((configuration == null) || !configuration.NoDesktop) - frameworkNameList.Add(".NETFramework"); - - if ((configuration == null) || !configuration.NoCompact) - { - frameworkNameList.Add(".NETCompactFramework"); - frameworkNameList.Add(".NETCompactFramework"); - frameworkNameList.Add(".NETCompactFramework"); - } - } - - if (frameworkVersionMap == null) - frameworkVersionMap = new VersionMap(); - - if ((configuration == null) || !configuration.NoDesktop) - { - VersionList desktopVersionList = new VersionList(); - - if ((configuration == null) || !configuration.NoNetFx20) - desktopVersionList.Add(new Version(2, 0, 50727)); - - if ((configuration == null) || !configuration.NoNetFx40) - desktopVersionList.Add(new Version(4, 0, 30319)); - - frameworkVersionMap.Add(".NETFramework", desktopVersionList); - } - - if ((configuration == null) || !configuration.NoCompact) - { - frameworkVersionMap.Add(".NETCompactFramework", new VersionList( - new Version[] { - new Version(2, 0, 0, 0), new Version(3, 5, 0, 0) - })); - } - - if (platformNameList == null) - { - platformNameList = new StringList(); - - if ((configuration == null) || !configuration.NoDesktop) - platformNameList.Add(null); - - if ((configuration == null) || !configuration.NoCompact) - { - platformNameList.Add("PocketPC"); - platformNameList.Add("Smartphone"); - platformNameList.Add("WindowsCE"); + private static void InitializeFrameworkList( + Configuration configuration, + ref FrameworkList frameworkList + ) + { + if (frameworkList == null) + frameworkList = new FrameworkList(); + + if (frameworkList.RootKey == null) + frameworkList.RootKey = Registry.LocalMachine; + + /////////////////////////////////////////////////////////////////// + + if (frameworkList.Names == null) + { + frameworkList.Names = new StringList(); + + if ((configuration == null) || !configuration.NoDesktop) + frameworkList.Names.Add(".NETFramework"); + + if ((configuration == null) || !configuration.NoCompact) + { + frameworkList.Names.Add(".NETCompactFramework"); + frameworkList.Names.Add(".NETCompactFramework"); + frameworkList.Names.Add(".NETCompactFramework"); + } + } + + /////////////////////////////////////////////////////////////////// + + if (frameworkList.Versions == null) + { + frameworkList.Versions = new VersionMap(); + + if ((configuration == null) || !configuration.NoDesktop) + { + VersionList desktopVersionList = new VersionList(); + + if ((configuration == null) || !configuration.NoNetFx20) + desktopVersionList.Add(new Version(2, 0, 50727)); + + if ((configuration == null) || !configuration.NoNetFx40) + desktopVersionList.Add(new Version(4, 0, 30319)); + + frameworkList.Versions.Add(".NETFramework", + desktopVersionList); + } + + if ((configuration == null) || !configuration.NoCompact) + { + frameworkList.Versions.Add(".NETCompactFramework", + new VersionList(new Version[] { + new Version(2, 0, 0, 0), new Version(3, 5, 0, 0) + })); + } + } + + /////////////////////////////////////////////////////////////////// + + if (frameworkList.PlatformNames == null) + { + frameworkList.PlatformNames = new StringList(); + + if ((configuration == null) || !configuration.NoDesktop) + frameworkList.PlatformNames.Add(null); + + if ((configuration == null) || !configuration.NoCompact) + { + frameworkList.PlatformNames.Add("PocketPC"); + frameworkList.PlatformNames.Add("Smartphone"); + frameworkList.PlatformNames.Add("WindowsCE"); } } } /////////////////////////////////////////////////////////////////////// @@ -2810,11 +3117,11 @@ rootKey, keyName, false, whatIf, verbose)) { if (key == null) return false; - if (platformName != null) // NOTE: Skip non-desktop frameworks. + if (platformName != null) // NOTE: Skip non-desktop. return true; string directory = GetFrameworkDirectory( rootKey, frameworkVersion, whatIf, verbose); @@ -2829,10 +3136,11 @@ } /////////////////////////////////////////////////////////////////////// private static bool ForEachFrameworkConfig( + FrameworkList frameworkList, FrameworkConfigCallback callback, string invariant, string name, string description, string typeName, @@ -2842,11 +3150,17 @@ bool verbose, ref bool saved, ref string error ) { - RegistryKey rootKey = frameworkRootKey; + if (frameworkList == null) + { + error = "invalid framework list"; + return false; + } + + RegistryKey rootKey = frameworkList.RootKey; if (rootKey == null) { error = "invalid root key"; return false; @@ -2857,45 +3171,45 @@ { error = "root key must be per-user or per-machine"; return false; } - if (frameworkNameList == null) + if (frameworkList.Names == null) { error = "no framework names found"; return false; } - if (frameworkVersionMap == null) + if (frameworkList.Versions == null) { error = "no framework versions found"; return false; } - if (platformNameList == null) + if (frameworkList.PlatformNames == null) { error = "no platform names found"; return false; } - if (frameworkNameList.Count != platformNameList.Count) + if (frameworkList.Names.Count != frameworkList.PlatformNames.Count) { error = String.Format("framework name count {0} does not " + - "match platform name count {1}", frameworkNameList.Count, - platformNameList.Count); + "match platform name count {1}", frameworkList.Names.Count, + frameworkList.PlatformNames.Count); return false; } - for (int index = 0; index < frameworkNameList.Count; index++) + for (int index = 0; index < frameworkList.Names.Count; index++) { // // NOTE: Grab the name of the framework (e.g. ".NETFramework") // and the name of the platform (e.g. "WindowsCE"). // - string frameworkName = frameworkNameList[index]; - string platformName = platformNameList[index]; + string frameworkName = frameworkList.Names[index]; + string platformName = frameworkList.PlatformNames[index]; // // NOTE: Skip all non-desktop frameworks (i.e. if the platform // name is not null). // @@ -2906,11 +3220,11 @@ // NOTE: Grab the supported versions of this particular // framework. // VersionList frameworkVersionList; - if (!frameworkVersionMap.TryGetValue( + if (!frameworkList.Versions.TryGetValue( frameworkName, out frameworkVersionList) || (frameworkVersionList == null)) { continue; } @@ -3008,18 +3322,25 @@ } /////////////////////////////////////////////////////////////////////// private static bool ForEachFrameworkRegistry( + FrameworkList frameworkList, FrameworkRegistryCallback callback, object clientData, bool whatIf, bool verbose, ref string error ) { - RegistryKey rootKey = frameworkRootKey; + if (frameworkList == null) + { + error = "invalid framework list"; + return false; + } + + RegistryKey rootKey = frameworkList.RootKey; if (rootKey == null) { error = "invalid root key"; return false; @@ -3030,53 +3351,53 @@ { error = "root key must be per-user or per-machine"; return false; } - if (frameworkNameList == null) + if (frameworkList.Names == null) { error = "no framework names found"; return false; } - if (frameworkVersionMap == null) + if (frameworkList.Versions == null) { error = "no framework versions found"; return false; } - if (platformNameList == null) + if (frameworkList.PlatformNames == null) { error = "no platform names found"; return false; } - if (frameworkNameList.Count != platformNameList.Count) + if (frameworkList.Names.Count != frameworkList.PlatformNames.Count) { error = String.Format("framework name count {0} does not " + - "match platform name count {1}", frameworkNameList.Count, - platformNameList.Count); + "match platform name count {1}", frameworkList.Names.Count, + frameworkList.PlatformNames.Count); return false; } - for (int index = 0; index < frameworkNameList.Count; index++) + for (int index = 0; index < frameworkList.Names.Count; index++) { // // NOTE: Grab the name of the framework (e.g. ".NETFramework") // and the name of the platform (e.g. "WindowsCE"). // - string frameworkName = frameworkNameList[index]; - string platformName = platformNameList[index]; + string frameworkName = frameworkList.Names[index]; + string platformName = frameworkList.PlatformNames[index]; // // NOTE: Grab the supported versions of this particular // framework. // VersionList frameworkVersionList; - if (!frameworkVersionMap.TryGetValue( + if (!frameworkList.Versions.TryGetValue( frameworkName, out frameworkVersionList) || (frameworkVersionList == null)) { continue; } @@ -3119,48 +3440,52 @@ #endregion /////////////////////////////////////////////////////////////////////// #region Per-Visual Studio Version Handling - private static void InitializeAllVsVersions( - Configuration configuration - ) - { - if (vsRootKey == null) - vsRootKey = Registry.LocalMachine; - - if (vsAdoNetTechnologyId == null) - vsAdoNetTechnologyId = new Guid( - "77AB9A9D-78B9-4BA7-91AC-873F5338F1D2"); - - if (vsPackageId == null) - vsPackageId = new Guid( - "DCBE6C8D-0E57-4099-A183-98FF74C64D9C"); - - if (vsServiceId == null) - vsServiceId = new Guid( - "DCBE6C8D-0E57-4099-A183-98FF74C64D9D"); - - if (vsDataSourcesId == null) - vsDataSourcesId = new Guid( - "0EBAAB6E-CA80-4B4A-8DDF-CBE6BF058C71"); - - if (vsDataProviderId == null) - vsDataProviderId = new Guid( - "0EBAAB6E-CA80-4B4A-8DDF-CBE6BF058C70"); - - if (vsVersionList == null) - { - vsVersionList = new VersionList(); - - // vsVersionList.Add(new Version(8, 0)); // Visual Studio 2005 + private static void InitializeVsList( + Configuration configuration, + ref VsList vsList + ) + { + if (vsList == null) + vsList = new VsList(); + + if (vsList.RootKey == null) + vsList.RootKey = Registry.LocalMachine; + + if (vsList.Versions == null) + { + vsList.Versions = new VersionList(); + + // vsList.Versions.Add(new Version(8, 0)); // Visual Studio 2005 + + if ((configuration == null) || !configuration.NoVs2008) + vsList.Versions.Add(new Version(9, 0)); // Visual Studio 2008 + + if ((configuration == null) || !configuration.NoVs2010) + vsList.Versions.Add(new Version(10, 0));// Visual Studio 2010 + } + + if (vsList.FrameworkVersions == null) + { + vsList.FrameworkVersions = new VersionListMap(); + + // vsList.FrameworkVersions.Add(new Version(8, 0), + // new VersionList(new Version[] { + // new Version(2, 0, 50727) })); if ((configuration == null) || !configuration.NoVs2008) - vsVersionList.Add(new Version(9, 0)); // Visual Studio 2008 + vsList.FrameworkVersions.Add(new Version(9, 0), + new VersionList(new Version[] { + new Version(2, 0, 50727) })); if ((configuration == null) || !configuration.NoVs2010) - vsVersionList.Add(new Version(10, 0));// Visual Studio 2010 + vsList.FrameworkVersions.Add(new Version(10, 0), + new VersionList(new Version[] { + new Version(2, 0, 50727), + new Version(4, 0, 30319) })); } } /////////////////////////////////////////////////////////////////////// @@ -3169,10 +3494,13 @@ Version vsVersion, bool whatIf, bool verbose ) { + if (vsVersion == null) + return false; + string format = "Software\\Microsoft\\VisualStudio\\{0}"; string keyName = String.Format(format, vsVersion); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) @@ -3199,22 +3527,26 @@ } /////////////////////////////////////////////////////////////////////// private static bool ForEachVsVersionRegistry( + VsList vsList, VisualStudioRegistryCallback callback, - Guid packageId, - Guid serviceId, - Guid dataSourceId, - Guid dataProviderId, + Package package, object clientData, bool whatIf, bool verbose, ref string error ) { - RegistryKey rootKey = vsRootKey; + if (vsList == null) + { + error = "invalid VS list"; + return false; + } + + RegistryKey rootKey = vsList.RootKey; if (rootKey == null) { error = "invalid root key"; return false; @@ -3225,17 +3557,17 @@ { error = "root key must be per-user or per-machine"; return false; } - if (vsVersionList == null) + if (vsList.Versions == null) { error = "no VS versions found"; return false; } - foreach (Version vsVersion in vsVersionList) + foreach (Version vsVersion in vsList.Versions) { TraceOps.Trace( TracePriority.Lower, traceCallback, String.Format( "vsVersion = {0}", ForDisplay(vsVersion)), traceCategory); @@ -3251,12 +3583,11 @@ if (callback == null) continue; if (!callback( - rootKey, vsVersion, packageId, serviceId, - dataSourceId, dataProviderId, clientData, whatIf, + rootKey, vsVersion, package, clientData, whatIf, verbose, ref error)) { return false; } } @@ -3608,27 +3939,72 @@ #region Visual Studio Handling private static string GetVsKeyName( Version vsVersion ) { + if (vsVersion == null) + return null; + return String.Format("Software\\Microsoft\\VisualStudio\\{0}", vsVersion); } + + /////////////////////////////////////////////////////////////////////// + + #region Visual Studio Version Handling + private static bool AddVsVersion( + RegistryKey rootKey, + Version vsVersion, + Package package, + object clientData, + bool whatIf, + bool verbose, + ref string error + ) + { + if (vsVersion != null) + { + VsList vsList = clientData as VsList; + + if (vsList != null) + { + if (vsList.InstalledVersions == null) + vsList.InstalledVersions = new VersionList(); + + if (!vsList.InstalledVersions.Contains(vsVersion)) + vsList.InstalledVersions.Add(vsVersion); + } + } + + return true; + } + #endregion /////////////////////////////////////////////////////////////////////// #region Visual Studio Data Source Handling private static bool AddVsDataSource( RegistryKey rootKey, Version vsVersion, - Guid dataSourceId, - Guid dataProviderId, + Package package, bool whatIf, bool verbose, ref string error ) { + if (vsVersion == null) + { + error = "invalid VS version"; + return false; + } + + if (package == null) + { + error = "invalid VS package"; + return false; + } + string keyName = GetVsKeyName(vsVersion); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { @@ -3651,19 +4027,20 @@ key); return false; } - using (MockRegistryKey dataSourceKey = RegistryHelper.CreateSubKey( - subKey, dataSourceId.ToString(VsIdFormat), whatIf, - verbose)) + using (MockRegistryKey dataSourceKey = + RegistryHelper.CreateSubKey(subKey, + package.DataSourceId.ToString(VsIdFormat), + whatIf, verbose)) { if (dataSourceKey == null) { error = String.Format( - "could not create registry key: {0}\\{1}", - key, dataSourceId.ToString(VsIdFormat)); + "could not create registry key: {0}\\{1}", key, + package.DataSourceId.ToString(VsIdFormat)); return false; } RegistryHelper.SetValue( @@ -3671,12 +4048,12 @@ "{0} Database File", ProjectName), whatIf, verbose); RegistryHelper.CreateSubKey(dataSourceKey, String.Format("SupportingProviders\\{0}", - dataProviderId.ToString(VsIdFormat)), whatIf, - verbose); + package.DataProviderId.ToString(VsIdFormat)), + whatIf, verbose); } } } return true; @@ -3685,16 +4062,28 @@ /////////////////////////////////////////////////////////////////////// private static bool RemoveVsDataSource( RegistryKey rootKey, Version vsVersion, - Guid dataSourceId, + Package package, bool whatIf, bool verbose, ref string error ) { + if (vsVersion == null) + { + error = "invalid VS version"; + return false; + } + + if (package == null) + { + error = "invalid VS package"; + return false; + } + string keyName = GetVsKeyName(vsVersion); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { @@ -3718,12 +4107,12 @@ return false; } RegistryHelper.DeleteSubKeyTree( - subKey, dataSourceId.ToString(VsIdFormat), whatIf, - verbose); + subKey, package.DataSourceId.ToString(VsIdFormat), + whatIf, verbose); } } return true; } @@ -3731,20 +4120,23 @@ /////////////////////////////////////////////////////////////////////// private static bool ProcessVsDataSource( RegistryKey rootKey, Version vsVersion, - Guid packageId, /* NOT USED */ - Guid serviceId, /* NOT USED */ - Guid dataSourceId, - Guid dataProviderId, + Package package, object clientData, bool whatIf, bool verbose, ref string error ) { + if (package == null) + { + error = "invalid VS package"; + return false; + } + AnyPair pair = clientData as AnyPair; if (pair == null) { error = "invalid VS callback data"; @@ -3752,18 +4144,16 @@ } if (pair.Y) { return AddVsDataSource( - rootKey, vsVersion, dataSourceId, dataProviderId, - whatIf, verbose, ref error); + rootKey, vsVersion, package, whatIf, verbose, ref error); } else { return RemoveVsDataSource( - rootKey, vsVersion, dataSourceId, whatIf, verbose, - ref error); + rootKey, vsVersion, package, whatIf, verbose, ref error); } } #endregion /////////////////////////////////////////////////////////////////////// @@ -3770,21 +4160,26 @@ #region Visual Studio Data Provider Handling private static bool AddVsDataProvider( RegistryKey rootKey, Version vsVersion, - Guid serviceId, - Guid dataProviderId, + Package package, string fileName, bool whatIf, bool verbose, ref string error ) { - if (vsAdoNetTechnologyId == null) + if (vsVersion == null) + { + error = "invalid VS version"; + return false; + } + + if (package == null) { - error = "invalid ADO.NET technology Id"; + error = "invalid VS package"; return false; } string keyName = GetVsKeyName(vsVersion); @@ -3810,19 +4205,20 @@ key); return false; } - using (MockRegistryKey dataProviderKey = RegistryHelper.CreateSubKey( - subKey, dataProviderId.ToString(VsIdFormat), whatIf, - verbose)) + using (MockRegistryKey dataProviderKey = + RegistryHelper.CreateSubKey(subKey, + package.DataProviderId.ToString(VsIdFormat), + whatIf, verbose)) { if (dataProviderKey == null) { error = String.Format( - "could not create registry key: {0}\\{1}", - key, dataProviderId.ToString(VsIdFormat)); + "could not create registry key: {0}\\{1}", key, + package.DataProviderId.ToString(VsIdFormat)); return false; } RegistryHelper.SetValue( @@ -3833,20 +4229,21 @@ dataProviderKey, "InvariantName", InvariantName, whatIf, verbose); RegistryHelper.SetValue( dataProviderKey, "Technology", - ((Guid)vsAdoNetTechnologyId).ToString(VsIdFormat), + package.AdoNetTechnologyId.ToString(VsIdFormat), whatIf, verbose); RegistryHelper.SetValue( dataProviderKey, "CodeBase", fileName, whatIf, verbose); RegistryHelper.SetValue( dataProviderKey, "FactoryService", - serviceId.ToString(VsIdFormat), whatIf, verbose); + package.ServiceId.ToString(VsIdFormat), whatIf, + verbose); RegistryHelper.CreateSubKey(dataProviderKey, "SupportedObjects\\DataConnectionUIControl", whatIf, verbose); @@ -3875,16 +4272,22 @@ /////////////////////////////////////////////////////////////////////// private static bool RemoveVsDataProvider( RegistryKey rootKey, Version vsVersion, - Guid dataProviderId, + Package package, bool whatIf, bool verbose, ref string error ) { + if (vsVersion == null) + { + error = "invalid VS version"; + return false; + } + string keyName = GetVsKeyName(vsVersion); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { @@ -3908,12 +4311,12 @@ return false; } RegistryHelper.DeleteSubKeyTree( - subKey, dataProviderId.ToString(VsIdFormat), whatIf, - verbose); + subKey, package.DataProviderId.ToString(VsIdFormat), + whatIf, verbose); } } return true; } @@ -3921,14 +4324,11 @@ /////////////////////////////////////////////////////////////////////// private static bool ProcessVsDataProvider( RegistryKey rootKey, Version vsVersion, - Guid packageId, /* NOT USED */ - Guid serviceId, - Guid dataSourceId, /* NOT USED */ - Guid dataProviderId, + Package package, object clientData, bool whatIf, bool verbose, ref string error ) @@ -3942,36 +4342,74 @@ } if (pair.Y) { return AddVsDataProvider( - rootKey, vsVersion, serviceId, dataProviderId, pair.X, + rootKey, vsVersion, package, pair.X, whatIf, verbose, ref error); } else { return RemoveVsDataProvider( - rootKey, vsVersion, dataProviderId, whatIf, verbose, - ref error); + rootKey, vsVersion, package, whatIf, + verbose, ref error); } } #endregion /////////////////////////////////////////////////////////////////////// #region Visual Studio Package Handling + private static void InitializeVsPackage( + ref Package package + ) + { + if (package == null) + { + package = new Package(); + + package.AdoNetTechnologyId = new Guid( + "77AB9A9D-78B9-4BA7-91AC-873F5338F1D2"); + + package.PackageId = new Guid( + "DCBE6C8D-0E57-4099-A183-98FF74C64D9C"); + + package.ServiceId = new Guid( + "DCBE6C8D-0E57-4099-A183-98FF74C64D9D"); + + package.DataSourceId = new Guid( + "0EBAAB6E-CA80-4B4A-8DDF-CBE6BF058C71"); + + package.DataProviderId = new Guid( + "0EBAAB6E-CA80-4B4A-8DDF-CBE6BF058C70"); + } + } + + /////////////////////////////////////////////////////////////////////// + private static bool AddVsPackage( RegistryKey rootKey, Version vsVersion, - Guid packageId, - Guid serviceId, + Package package, string fileName, bool whatIf, bool verbose, ref string error ) { + if (vsVersion == null) + { + error = "invalid VS version"; + return false; + } + + if (package == null) + { + error = "invalid VS package"; + return false; + } + string keyName = GetVsKeyName(vsVersion); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { @@ -3995,18 +4433,18 @@ return false; } using (MockRegistryKey packageKey = RegistryHelper.CreateSubKey( - subKey, packageId.ToString(VsIdFormat), whatIf, + subKey, package.PackageId.ToString(VsIdFormat), whatIf, verbose)) { if (packageKey == null) { error = String.Format( "could not create registry key: {0}\\{1}", - key, packageId.ToString(VsIdFormat)); + key, package.PackageId.ToString(VsIdFormat)); return false; } RegistryHelper.SetValue(packageKey, null, String.Format( @@ -4069,12 +4507,12 @@ return false; } RegistryHelper.SetValue( - subKey, packageId.ToString(VsIdFormat), ", 1000, 3", - whatIf, verbose); + subKey, package.PackageId.ToString(VsIdFormat), + ", 1000, 3", whatIf, verbose); } using (MockRegistryKey subKey = RegistryHelper.OpenSubKey( key, "Services", true, whatIf, verbose)) { @@ -4086,24 +4524,25 @@ return false; } using (MockRegistryKey serviceKey = RegistryHelper.CreateSubKey( - subKey, serviceId.ToString(VsIdFormat), whatIf, + subKey, package.ServiceId.ToString(VsIdFormat), whatIf, verbose)) { if (serviceKey == null) { error = String.Format( "could not create registry key: {0}\\{1}", - key, serviceId.ToString(VsIdFormat)); + key, package.ServiceId.ToString(VsIdFormat)); return false; } RegistryHelper.SetValue(serviceKey, null, - packageId.ToString(VsIdFormat), whatIf, verbose); + package.PackageId.ToString(VsIdFormat), whatIf, + verbose); RegistryHelper.SetValue(serviceKey, "Name", String.Format("{0} Designer Service", ProjectName), whatIf, verbose); } @@ -4116,17 +4555,28 @@ /////////////////////////////////////////////////////////////////////// private static bool RemoveVsPackage( RegistryKey rootKey, Version vsVersion, - Guid packageId, - Guid serviceId, + Package package, bool whatIf, bool verbose, ref string error ) { + if (vsVersion == null) + { + error = "invalid VS version"; + return false; + } + + if (package == null) + { + error = "invalid VS package"; + return false; + } + string keyName = GetVsKeyName(vsVersion); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { @@ -4150,11 +4600,12 @@ return false; } RegistryHelper.DeleteSubKeyTree( - key, packageId.ToString(VsIdFormat), whatIf, verbose); + key, package.PackageId.ToString(VsIdFormat), whatIf, + verbose); } using (MockRegistryKey subKey = RegistryHelper.OpenSubKey( key, "Menus", true, whatIf, verbose)) { @@ -4166,11 +4617,11 @@ return false; } RegistryHelper.DeleteValue( - subKey, packageId.ToString(VsIdFormat), whatIf, + subKey, package.PackageId.ToString(VsIdFormat), whatIf, verbose); } using (MockRegistryKey subKey = RegistryHelper.OpenSubKey( key, "Services", true, whatIf, verbose)) @@ -4183,11 +4634,11 @@ return false; } RegistryHelper.DeleteSubKeyTree( - subKey, serviceId.ToString(VsIdFormat), whatIf, + subKey, package.ServiceId.ToString(VsIdFormat), whatIf, verbose); } } return true; @@ -4196,14 +4647,11 @@ /////////////////////////////////////////////////////////////////////// private static bool ProcessVsPackage( RegistryKey rootKey, Version vsVersion, - Guid packageId, - Guid serviceId, - Guid dataSourceId, - Guid dataProviderId, + Package package, object clientData, bool whatIf, bool verbose, ref string error ) @@ -4217,27 +4665,29 @@ } if (pair.Y) { return AddVsPackage( - rootKey, vsVersion, packageId, serviceId, pair.X, whatIf, + rootKey, vsVersion, package, pair.X, whatIf, verbose, ref error); } else { return RemoveVsPackage( - rootKey, vsVersion, packageId, serviceId, whatIf, verbose, + rootKey, vsVersion, package, whatIf, verbose, ref error); } } #endregion #endregion /////////////////////////////////////////////////////////////////////// #region Application Entry Point - private static int Main(string[] args) + private static int Main( + string[] args + ) { Configuration configuration = null; string error = null; /////////////////////////////////////////////////////////////////// @@ -4244,24 +4694,35 @@ #region Command Line Processing if (!Configuration.FromArgs( args, true, ref configuration, ref error) || !Configuration.Process( - args, configuration, true, ref error)) + args, configuration, true, ref error) || + !Configuration.CheckRuntimeVersion( + configuration, true, ref error)) { TraceOps.ShowMessage( TracePriority.Highest, traceCallback, thisAssembly, error, traceCategory, MessageBoxButtons.OK, MessageBoxIcon.Error); - return 1; + return 1; /* FAILURE */ } + #endregion + + /////////////////////////////////////////////////////////////////// + + #region .NET Framework / Visual Studio Data + Package package = null; + FrameworkList frameworkList = null; + VsList vsList = null; /////////////////////////////////////////////////////////////////// - InitializeAllFrameworks(configuration); - InitializeAllVsVersions(configuration); + InitializeVsPackage(ref package); + InitializeFrameworkList(configuration, ref frameworkList); + InitializeVsList(configuration, ref vsList); #endregion /////////////////////////////////////////////////////////////////// AssemblyName assemblyName = AssemblyName.GetAssemblyName( @@ -4327,20 +4788,21 @@ /////////////////////////////////////////////////////////////////// #region .NET AssemblyFolders if (configuration.HasFlags(InstallFlags.AssemblyFolders, true)) { - if (!ForEachFrameworkRegistry(ProcessAssemblyFolders, + if (!ForEachFrameworkRegistry( + frameworkList, ProcessAssemblyFolders, directoryPair, configuration.WhatIf, configuration.Verbose, ref error)) { TraceOps.ShowMessage( - TracePriority.Highest, traceCallback, null, + TracePriority.Highest, traceCallback, thisAssembly, error, traceCategory, MessageBoxButtons.OK, MessageBoxIcon.Error); - return 1; + return 1; /* FAILURE */ } } #endregion /////////////////////////////////////////////////////////////////// @@ -4348,104 +4810,104 @@ #region .NET DbProviderFactory if (configuration.HasFlags(InstallFlags.DbProviderFactory, true)) { bool saved = false; - if (!ForEachFrameworkConfig(ProcessDbProviderFactory, + if (!ForEachFrameworkConfig( + frameworkList, ProcessDbProviderFactory, InvariantName, ProviderName, Description, FactoryTypeName, assemblyName, directoryPair, configuration.WhatIf, configuration.Verbose, ref saved, ref error)) { TraceOps.ShowMessage( - TracePriority.Highest, traceCallback, null, + TracePriority.Highest, traceCallback, thisAssembly, error, traceCategory, MessageBoxButtons.OK, MessageBoxIcon.Error); - return 1; + return 1; /* FAILURE */ } } #endregion /////////////////////////////////////////////////////////////////// #region VS Package if (configuration.HasFlags(InstallFlags.VsPackage, true)) { - if (!ForEachVsVersionRegistry(ProcessVsPackage, - (Guid)vsPackageId, (Guid)vsServiceId, - (Guid)vsDataSourcesId, (Guid)vsDataProviderId, - fileNamePair, configuration.WhatIf, - configuration.Verbose, ref error)) + if (!ForEachVsVersionRegistry( + vsList, ProcessVsPackage, package, fileNamePair, + configuration.WhatIf, configuration.Verbose, + ref error)) { TraceOps.ShowMessage( - TracePriority.Highest, traceCallback, null, + TracePriority.Highest, traceCallback, thisAssembly, error, traceCategory, MessageBoxButtons.OK, MessageBoxIcon.Error); - return 1; + return 1; /* FAILURE */ } } #endregion /////////////////////////////////////////////////////////////////// #region VS DataSource if (configuration.HasFlags(InstallFlags.VsDataSource, true)) { - if (!ForEachVsVersionRegistry(ProcessVsDataSource, - (Guid)vsPackageId, (Guid)vsServiceId, - (Guid)vsDataSourcesId, (Guid)vsDataProviderId, - fileNamePair, configuration.WhatIf, - configuration.Verbose, ref error)) + if (!ForEachVsVersionRegistry( + vsList, ProcessVsDataSource, package, fileNamePair, + configuration.WhatIf, configuration.Verbose, + ref error)) { TraceOps.ShowMessage( - TracePriority.Highest, traceCallback, null, + TracePriority.Highest, traceCallback, thisAssembly, error, traceCategory, MessageBoxButtons.OK, MessageBoxIcon.Error); - return 1; + return 1; /* FAILURE */ } } #endregion /////////////////////////////////////////////////////////////////// #region VS DataProvider if (configuration.HasFlags(InstallFlags.VsDataProvider, true)) { - if (!ForEachVsVersionRegistry(ProcessVsDataProvider, - (Guid)vsPackageId, (Guid)vsServiceId, - (Guid)vsDataSourcesId, (Guid)vsDataProviderId, - fileNamePair, configuration.WhatIf, - configuration.Verbose, ref error)) + if (!ForEachVsVersionRegistry( + vsList, ProcessVsDataProvider, package, fileNamePair, + configuration.WhatIf, configuration.Verbose, + ref error)) { TraceOps.ShowMessage( - TracePriority.Highest, traceCallback, null, + TracePriority.Highest, traceCallback, thisAssembly, error, traceCategory, MessageBoxButtons.OK, MessageBoxIcon.Error); - return 1; + return 1; /* FAILURE */ } } #endregion /////////////////////////////////////////////////////////////////// + #region Log Summary TraceOps.Trace( TracePriority.Higher, traceCallback, String.Format( "subKeysCreated = {0}, subKeysDeleted = {1}, " + "keyValuesSet = {2}, keyValuesDeleted = {3}", ForDisplay(RegistryHelper.SubKeysCreated), ForDisplay(RegistryHelper.SubKeysDeleted), ForDisplay(RegistryHelper.KeyValuesSet), ForDisplay(RegistryHelper.KeyValuesDeleted)), traceCategory); + #endregion /////////////////////////////////////////////////////////////////// - return 0; + return 0; /* SUCCESS */ } #endregion } #endregion }