Author: brett Date: Fri Jul 11 10:00:56 2014 New Revision: 1609664 URL: http://svn.apache.org/r1609664 Log: 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 Added: incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/util/ incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/util/WinRegistry.java Modified: incubator/npanday/npanday-its/trunk/pom.xml incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/AbstractNPandayIntegrationTestCase.java Modified: incubator/npanday/npanday-its/trunk/pom.xml URL: http://svn.apache.org/viewvc/incubator/npanday/npanday-its/trunk/pom.xml?rev=1609664&r1=1609663&r2=1609664&view=diff ============================================================================== --- incubator/npanday/npanday-its/trunk/pom.xml (original) +++ incubator/npanday/npanday-its/trunk/pom.xml Fri Jul 11 10:00:56 2014 @@ -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> Modified: incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/AbstractNPandayIntegrationTestCase.java URL: http://svn.apache.org/viewvc/incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/AbstractNPandayIntegrationTestCase.java?rev=1609664&r1=1609663&r2=1609664&view=diff ============================================================================== --- incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/AbstractNPandayIntegrationTestCase.java (original) +++ incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/AbstractNPandayIntegrationTestCase.java Fri Jul 11 10:00:56 2014 @@ -20,6 +20,7 @@ package npanday.its; */ 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.VerificationE 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.File; 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 @@ public abstract class AbstractNPandayInt 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; } } } Added: incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/util/WinRegistry.java URL: http://svn.apache.org/viewvc/incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/util/WinRegistry.java?rev=1609664&view=auto ============================================================================== --- incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/util/WinRegistry.java (added) +++ incubator/npanday/npanday-its/trunk/src/test/java/npanday/its/util/WinRegistry.java Fri Jul 11 10:00:56 2014 @@ -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; + } + } +}