find ildasm from the registry
Ensures correct one is found for x64 machines, otherwise it fails with an
error about trying to use a side-by-side install
git-svn-id: https://svn.apache.org/repos/asf/incubator/npanday/npanday-its/trunk@1609664 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 2f01746..383266c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -109,6 +109,11 @@
<version>1.3</version>
</dependency>
<dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>1.5.15</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>2.0</version>
diff --git a/src/test/java/npanday/its/AbstractNPandayIntegrationTestCase.java b/src/test/java/npanday/its/AbstractNPandayIntegrationTestCase.java
index ddc87f0..076a0eb 100644
--- a/src/test/java/npanday/its/AbstractNPandayIntegrationTestCase.java
+++ b/src/test/java/npanday/its/AbstractNPandayIntegrationTestCase.java
@@ -20,6 +20,7 @@
*/
import junit.framework.TestCase;
+import npanday.its.util.WinRegistry;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
@@ -27,6 +28,7 @@
import org.apache.maven.it.Verifier;
import org.apache.maven.it.util.FileUtils;
import org.apache.maven.it.util.ResourceExtractor;
+import org.apache.maven.it.util.StringUtils;
import org.apache.maven.it.util.cli.CommandLineException;
import org.apache.maven.it.util.cli.CommandLineUtils;
import org.apache.maven.it.util.cli.Commandline;
@@ -37,6 +39,7 @@
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -476,16 +479,28 @@
private static String findDisasmExec() {
String value = null;
- for (String path : new String[] { System.getenv("ProgramFiles"), System.getenv("ProgramFiles(x86)")}) {
- File[] versions = new File(path, "Microsoft SDKs\\Windows").listFiles();
- if (versions != null) {
- for (File f : versions) {
- File ildasm = new File(f, "bin\\ildasm.exe");
- if (ildasm.exists()) {
- value = ildasm.getAbsolutePath();
- disasmArg = "/text";
- System.out.println("Found ildasm at " + value + " for disassembly");
- }
+ String currentVersion = WinRegistry.getValue(WinRegistry.RegistryHKey.HKLM, "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows", "CurrentVersion");
+
+ String[] searchKeys = {
+ "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\12.0\\12.0@SDK40ToolsPath",
+ "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\4.0\\11.0@SDK40ToolsPath",
+ "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\4.0@SDK40ToolsPath",
+ "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\{currentVersion}\\WinSDK-NetFx40Tools@InstallationFolder",
+ "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\4.0@SDK35ToolsPath",
+ "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\{currentVersion}\\WinSDKNetFx35Tools@InstallationFolder"
+ };
+
+ for (String key : searchKeys) {
+ key = StringUtils.replace(key, "{currentVersion}", currentVersion);
+ String[] split = key.split("@");
+ String path = WinRegistry.getValue(WinRegistry.RegistryHKey.HKLM, split[0], split[1]);
+ if (path != null) {
+ File ildasm = new File(path, "ildasm.exe");
+ if (ildasm.exists()) {
+ value = ildasm.getAbsolutePath();
+ disasmArg = "/text";
+ System.out.println("Found ildasm at " + value + " for disassembly");
+ break;
}
}
}
diff --git a/src/test/java/npanday/its/util/WinRegistry.java b/src/test/java/npanday/its/util/WinRegistry.java
new file mode 100644
index 0000000..386b07f
--- /dev/null
+++ b/src/test/java/npanday/its/util/WinRegistry.java
@@ -0,0 +1,565 @@
+package npanday.its.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.codehaus.plexus.util.Os;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.prefs.Preferences;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class WinRegistry
+{
+ public static final int HKEY_CURRENT_USER = 0x80000001;
+
+ public static final int HKEY_LOCAL_MACHINE = 0x80000002;
+
+ public static final int REG_SUCCESS = 0;
+
+ private static final int KEY_ALL_ACCESS = 0xf003f;
+
+ private static final int KEY_READ = 0x20019;
+
+ private static Preferences userRoot = Preferences.userRoot();
+
+ private static Preferences systemRoot = Preferences.systemRoot();
+
+ private static Class<? extends Preferences> userClass = userRoot.getClass();
+
+ private static Method regOpenKey = null;
+
+ private static Method regCloseKey = null;
+
+ private static Method regQueryValueEx = null;
+
+ private static Method regEnumValue = null;
+
+ private static Method regQueryInfoKey = null;
+
+ private static Method regEnumKeyEx = null;
+
+ private static Method regCreateKeyEx = null;
+
+ private static Method regSetValueEx = null;
+
+ private static Method regDeleteKey = null;
+
+ private static Method regDeleteValue = null;
+
+ private static Pattern REGISTRY_REFERENCE_REGEX = Pattern.compile( "\\$\\(Registry:([A-Z_]+)\\\\(.*)@(.*)\\)" );
+
+ static
+ {
+ try
+ {
+ regOpenKey = userClass.getDeclaredMethod(
+ "WindowsRegOpenKey", new Class[]{ int.class, byte[].class, int.class }
+ );
+ regOpenKey.setAccessible( true );
+ regCloseKey = userClass.getDeclaredMethod( "WindowsRegCloseKey", new Class[]{ int.class } );
+ regCloseKey.setAccessible( true );
+ regQueryValueEx = userClass.getDeclaredMethod(
+ "WindowsRegQueryValueEx", new Class[]{ int.class, byte[].class }
+ );
+ regQueryValueEx.setAccessible( true );
+ regEnumValue = userClass.getDeclaredMethod(
+ "WindowsRegEnumValue", new Class[]{ int.class, int.class, int.class }
+ );
+ regEnumValue.setAccessible( true );
+ regQueryInfoKey = userClass.getDeclaredMethod( "WindowsRegQueryInfoKey1", new Class[]{ int.class } );
+ regQueryInfoKey.setAccessible( true );
+ regEnumKeyEx = userClass.getDeclaredMethod(
+ "WindowsRegEnumKeyEx", new Class[]{ int.class, int.class, int.class }
+ );
+ regEnumKeyEx.setAccessible( true );
+ regCreateKeyEx = userClass.getDeclaredMethod(
+ "WindowsRegCreateKeyEx", new Class[]{ int.class, byte[].class }
+ );
+ regCreateKeyEx.setAccessible( true );
+ regSetValueEx = userClass.getDeclaredMethod(
+ "WindowsRegSetValueEx", new Class[]{ int.class, byte[].class, byte[].class }
+ );
+ regSetValueEx.setAccessible( true );
+ regDeleteValue = userClass.getDeclaredMethod(
+ "WindowsRegDeleteValue", new Class[]{ int.class, byte[].class }
+ );
+ regDeleteValue.setAccessible( true );
+ regDeleteKey = userClass.getDeclaredMethod(
+ "WindowsRegDeleteKey", new Class[]{
+ int.class, byte[].class
+ }
+ );
+ regDeleteKey.setAccessible( true );
+ }
+ catch (NoSuchMethodException e){
+ // we are not on windows, then!
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public WinRegistry()
+ {
+ }
+
+ /**
+ * Read a value from key and value name
+ *
+ * @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+ * @param key
+ * @param valueName
+ * @return the value
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ * @throws java.lang.reflect.InvocationTargetException
+ *
+ */
+ public static String readString( int hkey, String key, String valueName ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ if ( hkey == HKEY_LOCAL_MACHINE )
+ {
+ return readString( systemRoot, hkey, key, valueName );
+ }
+ else if ( hkey == HKEY_CURRENT_USER )
+ {
+ return readString( userRoot, hkey, key, valueName );
+ }
+ else
+ {
+ throw new IllegalArgumentException( "hkey=" + hkey );
+ }
+ }
+
+ /**
+ * Read value(s) and value name(s) form given key
+ *
+ * @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+ * @param key
+ * @return the value name(s) plus the value(s)
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ * @throws java.lang.reflect.InvocationTargetException
+ *
+ */
+ public static Map<String, String> readStringValues( int hkey, String key ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ if ( hkey == HKEY_LOCAL_MACHINE )
+ {
+ return readStringValues( systemRoot, hkey, key );
+ }
+ else if ( hkey == HKEY_CURRENT_USER )
+ {
+ return readStringValues( userRoot, hkey, key );
+ }
+ else
+ {
+ throw new IllegalArgumentException( "hkey=" + hkey );
+ }
+ }
+
+ /**
+ * Read the value name(s) from a given key
+ *
+ * @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+ * @param key
+ * @return the value name(s)
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ * @throws java.lang.reflect.InvocationTargetException
+ *
+ */
+ public static List<String> readStringSubKeys( int hkey, String key ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ if ( hkey == HKEY_LOCAL_MACHINE )
+ {
+ return readStringSubKeys( systemRoot, hkey, key );
+ }
+ else if ( hkey == HKEY_CURRENT_USER )
+ {
+ return readStringSubKeys( userRoot, hkey, key );
+ }
+ else
+ {
+ throw new IllegalArgumentException( "hkey=" + hkey );
+ }
+ }
+
+ /**
+ * Create a key
+ *
+ * @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
+ * @param key
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ * @throws java.lang.reflect.InvocationTargetException
+ *
+ */
+ public static void createKey( int hkey, String key ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ int[] ret;
+ if ( hkey == HKEY_LOCAL_MACHINE )
+ {
+ ret = createKey( systemRoot, hkey, key );
+ regCloseKey.invoke( systemRoot, new Object[]{ new Integer( ret[0] ) } );
+ }
+ else if ( hkey == HKEY_CURRENT_USER )
+ {
+ ret = createKey( userRoot, hkey, key );
+ regCloseKey.invoke( userRoot, new Object[]{ new Integer( ret[0] ) } );
+ }
+ else
+ {
+ throw new IllegalArgumentException( "hkey=" + hkey );
+ }
+ if ( ret[1] != REG_SUCCESS )
+ {
+ throw new IllegalArgumentException( "rc=" + ret[1] + " key=" + key );
+ }
+ }
+
+ /**
+ * Write a value in a given key/value name
+ *
+ * @param hkey
+ * @param key
+ * @param valueName
+ * @param value
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ * @throws java.lang.reflect.InvocationTargetException
+ *
+ */
+ public static void writeStringValue( int hkey, String key, String valueName, String value ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ if ( hkey == HKEY_LOCAL_MACHINE )
+ {
+ writeStringValue( systemRoot, hkey, key, valueName, value );
+ }
+ else if ( hkey == HKEY_CURRENT_USER )
+ {
+ writeStringValue( userRoot, hkey, key, valueName, value );
+ }
+ else
+ {
+ throw new IllegalArgumentException( "hkey=" + hkey );
+ }
+ }
+
+ /**
+ * Delete a given key
+ *
+ * @param hkey
+ * @param key
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ * @throws java.lang.reflect.InvocationTargetException
+ *
+ */
+ public static void deleteKey( int hkey, String key ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ int rc = -1;
+ if ( hkey == HKEY_LOCAL_MACHINE )
+ {
+ rc = deleteKey( systemRoot, hkey, key );
+ }
+ else if ( hkey == HKEY_CURRENT_USER )
+ {
+ rc = deleteKey( userRoot, hkey, key );
+ }
+ if ( rc != REG_SUCCESS )
+ {
+ throw new IllegalArgumentException( "rc=" + rc + " key=" + key );
+ }
+ }
+
+ /**
+ * delete a value from a given key/value name
+ *
+ * @param hkey
+ * @param key
+ * @param value
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ * @throws java.lang.reflect.InvocationTargetException
+ *
+ */
+ public static void deleteValue( int hkey, String key, String value ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ int rc = -1;
+ if ( hkey == HKEY_LOCAL_MACHINE )
+ {
+ rc = deleteValue( systemRoot, hkey, key, value );
+ }
+ else if ( hkey == HKEY_CURRENT_USER )
+ {
+ rc = deleteValue( userRoot, hkey, key, value );
+ }
+ if ( rc != REG_SUCCESS )
+ {
+ throw new IllegalArgumentException( "rc=" + rc + " key=" + key + " value=" + value );
+ }
+ }
+
+ // =====================
+
+ private static int deleteValue( Preferences root, int hkey, String key, String value ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ int[] handles = (int[]) regOpenKey.invoke(
+ root, new Object[]{
+ new Integer( hkey ), toCstr( key ), new Integer( KEY_ALL_ACCESS )
+ }
+ );
+ if ( handles[1] != REG_SUCCESS )
+ {
+ return handles[1]; // can be REG_NOTFOUND, REG_ACCESSDENIED
+ }
+ int rc = (
+ (Integer) regDeleteValue.invoke(
+ root, new Object[]{
+ new Integer( handles[0] ), toCstr( value )
+ }
+ )
+ ).intValue();
+ regCloseKey.invoke( root, new Object[]{ new Integer( handles[0] ) } );
+ return rc;
+ }
+
+ private static int deleteKey( Preferences root, int hkey, String key ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ int rc = (
+ (Integer) regDeleteKey.invoke(
+ root, new Object[]{ new Integer( hkey ), toCstr( key ) }
+ )
+ ).intValue();
+ return rc; // can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS
+ }
+
+ private static String readString( Preferences root, int hkey, String key, String value ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ int[] handles = (int[]) regOpenKey.invoke(
+ root, new Object[]{
+ new Integer( hkey ), toCstr( key ), new Integer( KEY_READ )
+ }
+ );
+ if ( handles[1] != REG_SUCCESS )
+ {
+ return null;
+ }
+ byte[] valb = (byte[]) regQueryValueEx.invoke(
+ root, new Object[]{ new Integer( handles[0] ), toCstr( value ) }
+ );
+ regCloseKey.invoke( root, new Object[]{ new Integer( handles[0] ) } );
+ return ( valb != null ? new String( valb ).trim() : null );
+ }
+
+ private static Map<String, String> readStringValues( Preferences root, int hkey, String key ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ HashMap<String, String> results = new HashMap<String, String>();
+ int[] handles = (int[]) regOpenKey.invoke(
+ root, new Object[]{
+ new Integer( hkey ), toCstr( key ), new Integer( KEY_READ )
+ }
+ );
+ if ( handles[1] != REG_SUCCESS )
+ {
+ return null;
+ }
+ int[] info = (int[]) regQueryInfoKey.invoke( root, new Object[]{ new Integer( handles[0] ) } );
+
+ int count = info[2]; // count
+ int maxlen = info[3]; // value length max
+ for ( int index = 0; index < count; index++ )
+ {
+ byte[] name = (byte[]) regEnumValue.invoke(
+ root, new Object[]{
+ new Integer( handles[0] ), new Integer( index ), new Integer( maxlen + 1 )
+ }
+ );
+ String value = readString( hkey, key, new String( name ) );
+ results.put( new String( name ).trim(), value );
+ }
+ regCloseKey.invoke( root, new Object[]{ new Integer( handles[0] ) } );
+ return results;
+ }
+
+ private static List<String> readStringSubKeys( Preferences root, int hkey, String key ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ List<String> results = new ArrayList<String>();
+ int[] handles = (int[]) regOpenKey.invoke(
+ root, new Object[]{
+ new Integer( hkey ), toCstr( key ), new Integer( KEY_READ )
+ }
+ );
+ if ( handles[1] != REG_SUCCESS )
+ {
+ return null;
+ }
+ int[] info = (int[]) regQueryInfoKey.invoke( root, new Object[]{ new Integer( handles[0] ) } );
+
+ int count = info[0]; // count
+ int maxlen = info[3]; // value length max
+ for ( int index = 0; index < count; index++ )
+ {
+ byte[] name = (byte[]) regEnumKeyEx.invoke(
+ root, new Object[]{
+ new Integer( handles[0] ), new Integer( index ), new Integer( maxlen + 1 )
+ }
+ );
+ results.add( new String( name ).trim() );
+ }
+ regCloseKey.invoke( root, new Object[]{ new Integer( handles[0] ) } );
+ return results;
+ }
+
+ private static int[] createKey( Preferences root, int hkey, String key ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ return (int[]) regCreateKeyEx.invoke( root, new Object[]{ new Integer( hkey ), toCstr( key ) } );
+ }
+
+ private static void writeStringValue(
+ Preferences root, int hkey, String key, String valueName, String value ) throws
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException
+ {
+ int[] handles = (int[]) regOpenKey.invoke(
+ root, new Object[]{
+ new Integer( hkey ), toCstr( key ), new Integer( KEY_ALL_ACCESS )
+ }
+ );
+
+ regSetValueEx.invoke( root, new Object[]{ new Integer( handles[0] ), toCstr( valueName ), toCstr( value ) } );
+ regCloseKey.invoke( root, new Object[]{ new Integer( handles[0] ) } );
+ }
+
+ // utility
+ private static byte[] toCstr( String str )
+ {
+ byte[] result = new byte[str.length() + 1];
+
+ for ( int i = 0; i < str.length(); i++ )
+ {
+ result[i] = (byte) str.charAt( i );
+ }
+ result[str.length()] = 0;
+ return result;
+ }
+
+ public static String getValue(
+ RegistryHKey registryHKey, String key, String valueName ) {
+ if (!Os.isFamily( Os.FAMILY_WINDOWS ))
+ return null;
+
+ String value = null;
+ try {
+ value = WinRegistry.readString(registryHKey.getHKey(), key, valueName);
+ if (value != null) {
+ Matcher m = REGISTRY_REFERENCE_REGEX.matcher(value);
+ if (m.matches()) {
+ value = getValue(RegistryHKey.tryGetFromName(m.group(1)), m.group(2), m.group(3));
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ return value;
+ }
+
+ public static enum RegistryHKey
+ {
+ HKLM( "HKEY_LOCAL_MACHINE", 0x80000002 ),
+ HKCU( "HKEY_CURRENT_USER", 0x80000001 );
+
+ private String longName;
+ private int hkey;
+
+ RegistryHKey( String longName, int hkey )
+ {
+ this.longName = longName;
+ this.hkey = hkey;
+ }
+
+ public String getLongName()
+ {
+ return longName;
+ }
+
+ public int getHKey()
+ {
+ return hkey;
+ }
+
+ public static RegistryHKey tryGetFromName(String name){
+ if (name.equals("HKLM") || name.equals(HKLM.getLongName()))
+ return HKLM;
+ if (name.equals("HKCU") || name.equals(HKCU.getLongName()))
+ return HKCU;
+
+ return null;
+ }
+ }
+}