Showing posts with label registry. Show all posts
Showing posts with label registry. Show all posts

Monday, April 30, 2012

If It Ain't Broke...

Something that has always bothered me about a lot of folks who work in the "IT" field is this:  They insist that "newer is better" as knee-jerk perspective, while many of them drive old cars... by choice.  For example, when I had a discussion with a colleague who was adamant that VBScript and BAT are "dead" and PowerShell is the "future".  I countered that they are not dead, but that PowerShell is simply another guest at the party.  Then he countered with the "newer is better" mantra.  Then I asked why he still drives a 1968 Chevy Camaro SS.  He started to answer and then stumbled.  I followed with the following rationale...
  • Surely the "new" Camaro is engineered better (more efficient, safer, etc.)
  • The "new" Camaro has newer technology features
  • The "new" Camaro is built with more modern materials
So, why then does he not dump his '68 model for the 2013 model?

A-ha!

To be fair, it's not even about PowerShell.  It's not about any ONE language or technology.  It's about the whole mindset that one thing MUST replace another, rather than be enjoined to the community of potential tools to solve problems.  Medicine is a great example of this.  Even with the newest modern advances in medical technology and medical procedures, many of the most commonly used procedures date back decades, even centuries.  While the tools become more advanced, a drill is still a drill and a saw is still a saw.  Hopefully, you get where I'm going with this.

One tiny, little, itsy-bitsy example is this all-too-common approach to dealing with the Registry.  Someone says "hey!  I need you to delete a few Registry keys with a script... fast!"

You pull out the tool you know best, maybe it's VBScript, and you do something like this...

Dim WshShell, Value1, Value2

Value1= "HKEY_LOCAL_MACHINE\SOFTWARE\Fubar 2013\StupidKey1"
Value2="HKEY_CURRENT_USER\Software\Fubar 2013\StupidKey1"

Set WshShell = WScript.CreateObject("WScript.Shell")

On Error Resume Next
WshShell.RegDelete Value1
WshShell.RegDelete Value2

There's obviously nothing wrong with that approach.  But why not just do it with TWO lines of code using REG.exe and a CMD shell script?  Command Line tools are often very powerful and often more compact with regards to syntax.  Some that come to mind are DISM, APPCMD, REG, WMIC, SC, ROBOCOPY, and even CACLS and REGINI.

reg delete "HKLM\SOFTWARE\Fubar 2013\StupidKey1" /f
reg delete "HKCU\SOFTWARE\Fubar 2013\StupidKey1" /f

It really doesn't matter which two, or three, or six languages you want to compare and contrast.  Languages are tools.  Nothing more.  PERIOD.  Anyone who gets into a heated argument over which programming language is "best" deserves an open-hand smack.  Ok, enough of that, back to the discussion...

The ideal approach is to learn as many options as you can.  The more options the better.  You CANNOT learn too many options in any profession.  That is the crux of becoming a master at any trade.  Whether you are a carpenter, a painter, a brick mason, a surgeon, a soldier, or a programmer... the more options you learn the better equipped you'll be at facing unexpected or unfamiliar problems, and the faster you'll be at addressing the familiar problems, and more efficiently.  That is what they call "value-add".  Learning.

So, before you write something (or someone) off as obsolete, think again.  Maybe it's still useful. Maybe it's not really "broke".  Maybe the newer alternatives offer clear advantages in some situations, but not in *all* situations.  Rather than throwing out old options as a standard practice isn't really so good after all.  If it's still there, at least give it consideration.  You never know when the "old" option might be the "better" option.

Now, this is where my Perl colleagues will say "I can do that in one line" and chuckle.  I hate those guys.

Sunday, April 1, 2012

VLDB Code Example: Registry Functions

Basic examples of VLISP registry functions (vl-registry-write) and (vl-registry-read).  Note the double backslashes, which is common for escaped string characters in LISP...

(vl-registry-write "HKEY_CURRENT_USER\\Example1" "FOO" "123")

Result: "123"

(vl-registry-read "HKEY_CURRENT_USER\\Example1" "FOO")

Result: "123"

(vl-registry-read "HKEY_CURRENT_USER\\Example1")

Result: nil

(vl-registry-write "HKEY_CURRENT_USER\\Example2" "" "ABCDEF")

Result: "ABCDEF"

(vl-registry-read "HKEY_CURRENT_USER\\Example2")

Result: "ABCDEF"

A simple abstracted "get" and "set" function pair using a custom Registry base location...

(setq G$REGROOT "HKEY_CURRENT_USER\\Software\\MyApplication\\")

(defun RegGet (key default / val)
    (if (= nil (setq val (vl-registry-read (strcat G$REGROOT key))))
        (progn
            (RegSet key default)
            (setq val (vl-registry-read (strcat G$REGROOT key)))
        )
    )
    (if val val default)
)

(defun RegSet (key val)
    (vl-registry-write (strcat G$REGROOT key) "" val)
)

Monday, September 26, 2011

Automation Gyration

I recently updated some information on my tabular matrix of "Windows 7 Automation Options" over at my other other other web site.  The goal of this matrix is to map out alternative ways to perform common administrative tasks and compare which is best for certain conditions or situations.  Let me know if you want something added or if you have a correction to offer.

11 Ways to Manipulate the Windows Registry

  • Direct via REGEDIT
  • Command line using REG.exe
  • Import via .REG file (invokes REGEDIT)
  • COM Scripting: VBscript, KiXtart, Perl, Javascript, etc.
  • .NET Scripting: PowerShell
  • Group Policy
  • Group Policy Preferences
  • .MSI installer
  • .EXE application
  • Stream Interface: Java
  • Temp Labor:  Order Timmy to do it

Friday, June 10, 2011

Mapping Out Windows 7 Automation Options

This is another one of those projects I’ve had swimming around in the back of my puny brain for a long time.  Think of it like an ant rollerskating around the inside of a vacant Walmart building.  Yeah.  Kind of like that.

The idea was to map out various “common” IT chores against the four most common methods for automating them and checking which ones work best and which are the “easiest” to implement.  Is it perfect?  Ha!  If you know anything about me you’ll know it’s at least sincere and fairly thorough, but I cannot claim 100% accuracy.  It is a living document since I’m using one of Google’s coolest and most flexible tools: Google Sites List Page template.  It lets you define your own list structures, including data types per column (text, date, URL, checkbox, drop-down, etc.) and specify the default sorting options. 

I plan on adding to this and updating it as time permits and as something new comes up.  I welcome any input and corrections, so chime in and I will be sure to post credit for submissions/corrections on the page.  I hope it helps system admins to more quickly pick an option to solve an automation challenge using one of the many built-in features of Windows 7 and Windows Server 2008 R2.

https://sites.google.com/site/skatterbrainz/automation

Please check it out and let me know what you think?  Thank you!

Tuesday, May 10, 2011

AutoCAD Profiles

What is a Profile?

An AutoCAD "profile" is a named collection of configuration settings.  A Profile may include options that control display, modeling, user interaction, printing and plotting, saving, importing and exporting, units of measurement, and so on.  There are essentially two types of "Preferences" in the AutoCAD environment: Application and Database.  "Database" is another word for "Drawing" in this context, so "Database Preferences" translates into "Drawing Preferences" or configuration settings that are drawing level or drawing-specific.

How are they stored?

They are actually stored as Windows Registry keys under the path: HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\R18.2\ACAD-A001:409\Profiles\

The first profile created by default is the "<<Unnamed Profile>>" but as you create new profiles they will be added under the \Profiles\ path as well.

How are Profiles accessed and controlled?

There are several ways to get at profiles.

  • From the OPTIONS dialog forms within AutoCAD
  • From the Windows Registry
  • From exported .ARG files
  • From programmatic interfaces like COM and .NET

The first method is pretty simple and self-explanatory. So let's dig into the others.

The Windows Registry is where profiles are stored and maintained.  When you create a new Profile within the OPTIONS dialog, it creates a new sub-tree with the corresponding name and populates it with all the pertinent keys and values to store the profile configuration.

If you export the profile from within the OPTIONS dialog, it creates an .ARG file.  This is actually a .REG file (a Windows Registry export file format), so you can very easily rename a .ARG to .REG and use it like any other Registry data file (import, export, archive, etc.)

The programmatic interfaces for accessing and manipulating profile data are most often via .NET or the older COM interfaces.  Because they are stored in the Windows Registry, ANY other programmatic interfaces that can manipulate the registry can be used as well.  When it comes to leveraging .NET interfaces, you can pretty much narrow that down to Visual Studio tools like VB.NET, C#.NET, PowerShell, as well as ObjectARX®   When it comes to COM interfaces, you can use anything that talks COM.  Some examples include VBscript, Javascript, KiXtart, PowerShell.

Programmatic Access to Preferences

VB.NET

Dim acPrefComObj As AcadPreferences = Application.Preferences

C#

AcadPreferences acPrefComObj = (AcadPreferences)Application.Preferences;

VBA

Dim acadPref As AcadPreferences
Set acadPref = ThisDrawing.Application.Preferences

Visual LISP

(setq objAcad (vlax-get-acad-object))
(setq objAcadPrefs (vla-get-Preferences objAcad))

Windows Scripting Host - VBScript

Because VBScript is external to the AutoCAD application environment, it must first obtain an object instance of the AcadApplication class in order to begin drilling into the internal objects, properties, methods and so on.

Dim objAcad, objAcadPrefs
Set objAcad = CreateObject("AutoCAD.Application")
Set objAcadPrefs = objAcad.Preferences

Programmatic Access to Profiles

VB.NET

Dim acadApp As AcadApplication = CType(Application.AcadApplication, AcadApplication)
acadApp.Preferences.Profiles.ExportProfile("PROFILE_NAME", "C:\test.arg")

This is one way to get at Profiles from within an AutoCAD session environment.

Visual LISP

This is (or these are) another example of getting at Profiles from within AutoCAD.

example: linear expression…

(setq objActProfile (vla-get-ActiveProfile (vla-get-Profiles (vla-get-Preferences (vlax-get-Acad-Object)))))

example: unfactored collection of expressions

(setq objAcadApp (vlax-get-Acad-Object))
(setq objAcadPrefs (vla-get-Preferences objAcad))
(setq objProfiles (vla-get-Profiles objAcadPrefs))
(setq objActProfile (vla-get-ActiveProfile objProfiles))
(vla-ExportProfile objProfiles "Fubar" "c:\fubar.arg")

Windows Scripting Host - VBScript

This is an example of getting at profiles from outside of AutoCAD.

The downside to accessing the Profile collection via a non-object interface is that you don't get the nice object-oriented methods and syntax that make it kind of neat-o to use.  So instead of crawling the object tree, as it were, you have to fetch each entity as a distinct data value.

setq objShell = CreateObject("Wscript.Shell")
path = objShell.RegRead("HKCU\Software\Autodesk\AutoCAD\R18.2\ACAD-A001:409\Profiles\MyProfile\ACAD")
For each folderName in Split(path, ";")
    wscript.echo folderName
Next

Keep in mind that the Wscript.Shell RegRead() method is only useful on the local computer.  But this isn't really an obstacle since you don't really want to access HKCU on a remote computer (you have to first map the user SID to obtain the HKEY_USERS path because HKCU is a pseudo registry hive that exists only under the local user context).  So… you can do it, but you have to ask yourself if it's really the best approach to getting at things on a remote computer.  Why not invoke the interface under the local user context?

PowerShell

$a = get-item HKCU:\Software\Autodesk\AutoCAD\R18.2\ACAD-A001:409\Profiles
$a.SubKeyCount <-- returns the number of profile trees beneath the Profiles path
$a.GetSubKeyNames() <-- enumerates the profile names

The upside to using PowerShell over VBscript is that you can invoke object programming techniques.  This is because $a (in this example) is actually an object instance.  There are other ways to employ PowerShell, so don't think this is the only possible approach (it's barely scratching the surface).

Group Policy Preferences

That's right.  As astounding as it may be, I have long ago recommended Windows admins explore the use of Group Policy Preferences for managing and manipulating computer settings with less effort than scripting typically requires.

But you say "Dave?! How can you suggest we leave scripting out in the cold, starving and dying of neglect?!  How cruel!"

Fair enough.  But once you see how easy it is to create, modify and delete registry keys and values on a bazillion computers, you will look at your old login and startup scripts like the old girlfriend you dumped years ago (and never regretted).

Possibilities

They are almost endless.  For example, using the available tools and technologies, you can rig up a way to automatically reset profiles for classroom settings (if you don't use virtual machines to handle state management).  You can deploy and update a standard profile for specific business groups, locations or for the entire operation.  If a path reference is set in a default profile, but later needs to be changed (and you didn't map it to a DFS target) you can push out a fix using scripts or even a Windows Group Policy Preferences object setting.

Conclusion / Summary / Mumbo-Jumbo Ay Carumbo!

I have no intention of trying to create an ebook expose to exhause every conceivable way you can get at Profiles, create, rename, modify, delete, import or export them.  I also did not intend to cover every programming language or programmatic option available or possible.  The goal here is to simply show the following:

  1. The Preferences and Profiles items are structured and fairly well-defined
  2. They are accessible from a lot of different angles using a lot of different tools
  3. You have choices and options at your disposal

That said: go forth and hack away.  Just don't call me if you break anything.

Friday, December 17, 2010

Book: The Packagers Pocket Reference

The book is now available for purchase on Amazon for $2.99.  That's right $2.99.  You can't even buy a Starbucks "tall" latte for that much.  Buy it now for Amazon Kindle and Kindle Reader apps!

ppr_cover

Here's an added offer: If you buy it, and spot something glaringly wrong or missing or incomplete, and let me know, I will add your name to the Acknowledgements list.  But that's not all.  If your feedback is relevant and results in updating the book, I will send you the revised follow-up edition for free.

Wednesday, December 15, 2010

Book: The Packager's Pocket Reference

ppr_coverI just submitted this to Amazon for publishing.  Same Kindle format, but this time the price is (are you sitting down?…) $2.99   I will post more information as soon as it is available for purchase.

I've included the table of contents below to help explain what is included.  Heck, for $2.99 it's not bad.

 

 

 

 

 

 

Contents

Overview and Introduction 5

Registry - Uninstall Keys6

32-bit Windows Apps: 6

64-bit Windows Apps: 6

32-bit Apps on 64-bit Windows: 6

Command Line Tools 7

Windows Services 7

Stopping a Service: 7

Deleting a Service: 7

List all Services on Remote Computer: 7

List Details on Specific Service on Remote Computer: 7

Processes 7

List Running Process: 7

List all Instances of Fubar.exe Processes: 7

Kill a Process by Process ID Number: 7

Kill a Process by Name: 7

Kill a Remote Process by Name: 7

Registry Data 8

Query a (local) Registry Key and Sub-Keys: 8

Query a (local) Registry Key and all Values below it: 8

Query a (remote) Registry Key and Sub-Keys 8

Create or Replace a Registry Key: 8

Create or Replace a Registry Key [default] Value: 8

Query AutoCAD 2011 Profiles: 8

Extract a Profile to a .REG file 8

MSIEXEC 8

Installation and Uninstall Parameters 8

MSIEXEC errors 9

Setup.exe Techniques 9

Record a Setup Log File 9

Silent Install Using a Setup Log File 9

Silent Uninstall Using a Setup Log File 9

Folder Permissions 9

Registry Permissions 10

REGINI.exe 10

Wise Package Scripting 10

Adjusting Folder Permissions During Install: 10

Delete Left Folders and Files During Uninstall: 10

Delete Registry Keys During Uninstall: 10

AutoCAD® Customization 11

Enforced Custom Profile 11

Create a User Profile and Desktop Shortcut 11

Preparation Steps: 11

CMD Script: 11

Common Silent Installations 12

Common Silent Uninstalls 12

Detection Methods 14

File/Folder-Based 14

Registry-Based 14

System Center Configuration Manager 2007 17

WQL search expressions 17

AutoCAD 2011 17

Tip: Maintenance Windows 17

Tip: DirectX Deployments 17

FlexLM© Client Settings 17

Server Names Environment Variable 17

Server Request TimeOut Adjustment: 17

Recipes 18

Detect a Folder 18

Detect a Registry Key 19

Delete a Folder Tree 19

Add or Change a Registry Key 20

Add or Change a Registry Value 20

Delete a Registry Key 21

Get File Version Information 21

CMD Script Path Expansion Variables 22

Change FlexLM© License Server List on Multiple Remote Computers 22

Solution 1: Use REG.exe and a script 24

Solution 2: Use PsExec.exe in a script with a script 24

Make and Run a REGINI Operation from VBScript 25

Registry Key Detection: 32-bit vs 64-bit 25

Robocopy Backups and Mirroring 26

Backup only newer files with Robocopy 26

Maintain Synchronization Between Two Folders: 26

Appendix A - API References 27

Appendix B - Useful Web Sites 28

Acknowledgements 28

Saturday, December 4, 2010

Deploy Registry Updates to Multiple Computers

Challenge:

You need to modify a specific registry key or value on 50, 500 or 5,000 computers on your network.  You need to get it done in the next 15 minutes.  Your boss is standing over you with a can of pepper spray and a taser.  The HR manager has a pink slip ready, the name is not yet filled out.  They are tapping their fingers and breathing heavily.  The pressure is on. …


Solution 1: Use REG.exe and a script

Solution 1 - Steps:

  1. Create a list (text file) containing the names of computers (ex. "computers.txt")
  2. Create a script to read the text file list, and run REG ADD <params> on each computer
  3. Open CMD and run the script

Example Script for Solution 1:

@echo off
FOR /F "tokens=1 delims=," %%G IN (computers.txt) DO (
    @echo %%G
    reg add \\%%G\HKLM\Software\Test /v Vname /d 123 /t REG_SZ /f
)


Solution 2: Use PsExec.exe in a script with a script

Solution 2 - Steps:

  1. Create a list (text file) containing the names of computers (ex. "computers.txt")
  2. Export the registry data from a reference computer (ex. "regdata.reg")
  3. Open CMD and run the following (example code only):

    psexec @computers.txt reg import \\server\share\regdata.reg

Friday, December 3, 2010

REG.exe vs REG.exe

I don't know this never hit me before today, but REG.exe got a shot of steroids after Windows XP.  The changes are awesome and I have become so comfortable with how it behaves on Windows 7 that I forgot that /F wasn't available on XP.  Damn if that isn't a powerful little feature.

WINDOWS XP

C:\>reg query /?
 
Console Registry Tool for Windows - version 3.0
Copyright (C) Microsoft Corp. 1981-2001.  All rights reserved
 
 
REG QUERY KeyName [/v ValueName | /ve] [/s]
 
  KeyName    [\Machine\]FullKey
    Machine - Name of remote machine,  omitting defaults to the current machine Only HKLM and HKU are available on remote machines
    FullKey  - in the form of ROOTKEY\SubKey name ROOTKEY  [ HKLM | HKCU | HKCR | HKU | HKCC ]
    SubKey  - The full name of a registry key under the selected ROOTKEY
  /v  query for a specific registry key ValueName  - The name, under the selected Key, to query if omitted, all values under the Key are queried
  /ve query for the default value or empty value name <no name>
  /s  queries all subkeys and values
 
Examples:
 
  REG QUERY HKLM\Software\Microsoft\ResKit /v Version
    Displays the value of the registry value Version
 
  REG QUERY HKLM\Software\Microsoft\ResKit\Nt\Setup /s
    Displays all subkeys and values under the registry key Setup
 
 
WINDOWS 7
 
C:\ >reg query /?
 
REG QUERY KeyName [/v [ValueName] | /ve] [/s] [/f Data [/k] [/d] [/c] [/e]] [/t Type] [/z] [/se Separator]
 
  KeyName  [\\Machine\]FullKey
           Machine - Name of remote machine, omitting defaults to the current machine. Only HKLM and HKU are available on remote machines
           FullKey - in the form of ROOTKEY\SubKey name
                ROOTKEY - [ HKLM | HKCU | HKCR | HKU | HKCC ]
                SubKey  - The full name of a registry key under the selected ROOTKEY
 
  /v       Queries for a specific registry key values.  If omitted, all values for the key are queried.
 
           Argument to this switch can be optional only when specified along with /f switch. This specifies to search in value names only.
 
  /ve      Queries for the default value or empty value name (Default).
 
  /s       Queries all subkeys and values recursively (like dir /s).
 
  /se      Specifies the separator (length of 1 character only) in data string for REG_MULTI_SZ. Defaults to "\0" as the separator.
 
  /f       Specifies the data or pattern to search for.  Use double quotes if a string contains spaces. Default is "*".
 
  /k       Specifies to search in key names only.
 
  /d       Specifies the search in data only.
 
  /c       Specifies that the search is case sensitive.  The default search is case insensitive.
 
  /e       Specifies to return only exact matches.  By default all the matches are returned.
 
  /t       Specifies registry value data type.
           Valid types are:   REG_SZ, REG_MULTI_SZ, REG_EXPAND_SZ, REG_DWORD, REG_QWORD, REG_BINARY, REG_NONE
           Defaults to all types.
 
  /z       Verbose: Shows the numeric equivalent for the type of the value name.
 
Examples:
 
  REG QUERY HKLM\Software\Microsoft\ResKit /v Version
    Displays the value of the registry value Version
 
  REG QUERY \\ABC\HKLM\Software\Microsoft\ResKit\Nt\Setup /s
    Displays all subkeys and values under the registry key Setup  on remote machine ABC
 
  REG QUERY HKLM\Software\Microsoft\ResKit\Nt\Setup /se #
    Displays all the subkeys and values with "#" as the seperator  for all value names whose type is REG_MULTI_SZ.
 
  REG QUERY HKLM /f SYSTEM /t REG_SZ /c /e
    Displays Key, Value and Data with case sensitive and exact occurrences of "SYSTEM" under HKLM root for the data type REG_SZ
 
  REG QUERY HKCU /f 0F /d /t REG_BINARY
    Displays Key, Value and Data for the occurrences of "0F" in data  under HKCU root for the data type REG_BINARY
 
  REG QUERY HKLM\SOFTWARE /ve
    Displays Value and Data for the empty value (Default)  under HKLM\SOFTWARE

Tuesday, November 23, 2010

How to Know if Your Autodesk Product is a Network Client

  1. Verify you even have a FlexLM or FlexNet server
  2. Type ABOUT and click the Product Information button
  3. Look at the software media box (should show in the label)
  4. Look in the Registry…
    HKLM\SOFTWARE\Autodesk\AutoCAD\Rxx.x\ACAD-xxxx:409
    ValueName: StandaloneNetworkType (3 = network)
    >> for example, with AutoCAD Civil 3D 2011…
    HKLM\SOFTWARE\Autodesk\AutoCAD\R18.1\ACAD-9000:409
    StandaloneNetworkType: 3 (REG_DWORD: 0x00000003)
  5. Ask  your Reseller
  6. Check the PO or invoice

Thursday, September 30, 2010

Software Packaging Tip: Adjusting Permissions

If you work within an environment where “users” are actually “users” and not Administrators of their computers, you will likely run into situations where some applications won’t function properly because the user doesn’t have permissions to modify the contents of certain folders or registry keys and values.

There are two basic tools for handling this and they’re both free and very easy to use, whether you prefer Wise, InstallShield, or good old fashioned scripting:

CACLS.exe (for files and folders)

REGINI.exe (for registry keys)

I won’t bother going into a lot of detail on these, because there’s tons of info already on the web for both of them, but they work and they work well.

In Wise, for example, you can edit your package to add a “Custom Action” to invoke either command.  CACLS is much easier to use because you just need to specify the file or folder you wish to modify, and then specify who gets what permissions to it. 

Example:

CACLS <path> <options> <user/group>:<permission>

CACLS “c:\acme” /T /E /C /G Users:C

The example above grants members of the local group “Users” the “Change” permission to C:\ACME and all sub-folders and files beneath it.  Keep in mind that if you need to specify a group name that has spaces in it, you need to wrap the name in double-quote (as shown below):

CACLS “c:\acme” /T /E /C /G “Domain Users”:C

There’s a good reference for this command at http://ss64.com/nt/cacls.html

REGINI on the other hand expects a file to be specified as the input to dictate which registry keys get what permissions.  Thankfully, with REGINI in particular, you can wrap all of it inside a script that writes its own input file.  With Wise you can then use the “Execute VBScript from Embedded” and wrap the .VBS file into the package itself.

Example:

regFile = “c:\windows\temp\reg.txt”
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set f = fso.OpenTextFile(regFile, 2, True)
f.WriteLine “HKEY_LOCAL_MACHINE\Software\ACME [1 5 7 11 17]”
f.Close
Set oShell = CreateObject("WScript.Shell")
oShell.Run "regini " & regFile, 8, true
f.Delete


This little bit of script creates the input file “reg.txt” in the TEMP folder beneath C:\WINDOWS, then uses the shell object to run REGINI.exe with the file input.  When it’s finished, it deletes the input file.  I adapted it from http://support.microsoft.com/?kbid=237607  so I can’t claim original authorship.  That other version is nice because they use the GetTempName method to generate a random filename instead of a static name, but that’s just fascinating for people with no life, like myself.



You can also do this very simply with a .BAT or .CMD script…



@echo off
echo HKEY_LOCAL_MACHINE\Software\ACME [1 5 7 11 17] >%temp%\reg.txt
regini %temp%\reg.txt


The point is: you have options. And “free” options are always nice.



My final parting advice: NEVER give user administrative rights to their computers.  It’s an admission of failure.  Find out what specific things need to be opened up and do it selectively, and carefully.  If you don’t have time to do that, do you have time to mop up the mess they create from installing a dozen shareware applications, two dozen worms, trojans and viruses (or virii?)?  Saving time now may end up costing you five times that later.  When users bitch and moan (that’s what they do best, right?) push back.  Demand that they identify WHY they absolutely need admin rights.  Find out what things they need to modify, and WHY and then work from there.  Don’t just give them the keys and let them go.  That’s insane.  This method works fine. I do it all the time and so do hundreds of other IT folks.

Monday, September 27, 2010

Ways to Modify (or Destory) the Registry

Invoke regedit.exe with .REG file
Interfaces:          GUI, script
Access:                 Local or Remote
Benefits:              Simple
Caveats:               Exposes data in .REG file

WMI StdRegProv class
Interfaces:          Script, Application
Access:                 Local or Remote
Benefits:              Cloak/Obfuscate data, run hidden
Caveats:               Firewalls and Remote Registry services (remote), scripting knowledge

WSH RegRead, RegWrite, RegDelete methods
Interfaces:          Script, Application
Access:                 Local
Benefits:              Cloak/Obfuscate data, run hidden
Caveats:               No remote access

Wise/InstallShield Compiled EXE
Interfaces:          GUI or hidden, Script, Application
Access:                 Local
Benefits:              Cloak/Obfuscate data, run hidden
Caveats:               Requires Wise Package Studio or AdminStudio and some scripting knowledge

REG.exe command
Interfaces:          GUI, script (shell)
Access:                 Local or Remote
Benefits:              Simple and consistent
Caveats:               Exposes data in stream

Proprietary Utility
Interfaces:          GUI (usually), cmd shell (sometimes), API call (rarely)
Access:                 Local or Remote
Benefits:              Easy GUI layout and options (typically)
Caveats:               Vendor lock-in, updates, etc., may require .NET or JRE also

Manual (REGEDIT.exe)
Interfaces:          GUI
Access:                 Local
Benefits:              Familiar
Caveats:               Does not scale well

Group Policy Preferences
Interfaces:          GUI (GPMC MMC console)
Access:                 Active Directory via client-side processing
Benefits:              Simple to configure and mass-deploy
Caveats:               Requires Active Directory environment.  Connected clients (receive policy changes)

I’m sure there are others I overlooked, but who cares.  Isn’t this enough? I mean, come on. Really?!

Monday, April 26, 2010

Windows 7, MSG.EXE and Group Policy Preferences

So, as of Windows Vista, NET SEND is gone.  But you want to send a console message via popup to a remote user or computer?  Windows Vista shipped with the MSG.EXE utility, which is still around in Windows 7.  But there’s a small problem, which led me to another small problem, but thankfully there’s an easy solution.

Problem 1 – You may need to modify a Registry Value on all your networked Windows 7 computers.

  • HKLM\SYSTEM\CurrentControlSet\Control\TerminalServer
  • Value: AllowRemoteRPC
  • Required value: 1 (REG_DWORD)

Problem 2 – Trying to set that on a remote Windows 7 box

The Remote Registry service is disabled by default.  You can start turning on services manually, but…

Solution – Use Group Policy Preferences to do it all at once

  1. Create a new GPO named something that makes sense
  2. Edit the new GPO
  3. Expand Computer Configuration / Preferences / Windows Settings
  4. Click on Registry
  5. Right-click and select New –> Registry Item
  6. Select Action: Update, Hive: HKEY_LOCAL_MACHINE
  7. Key Path: browse to the key shown above
  8. Select the Value name: AllowRemoteRPC
  9. Set the Value data: 1, specify type REG_DWORD
  10. Click OK

If you also want to enable remote Registry editing…

  1. Expand “Control Panel Settings”
  2. Select “Services”
  3. Right-click and select New –> Service
  4. Startup: Automatic, Service Name “Remote Registry”, Service Action: Start Service
  5. Click the Recovery tab
  6. Specify First and Second failure action as “Restart the Service”
  7. Specify Restart fail count after to 1 day, Restart service after 1 minute
  8. Click OK

Saturday, January 23, 2010

Remove DLL Register/Unregister Using PsExec

Problem:

You want to register or unregister a .DLL file on a remote computer, but
you do not want to (or cannot) remote in with Carbon Copy, Remote
Desktop, etc.

Solution:

Use Microsoft Sysinternals "PSEXEC" to invoke the process remotely.
How:

  1. Download psexec.exe from http://live.sysinternals.com/tools and save
    it to a folder on your C: drive
  2. Open a CMD console using RunAs and your Admin-level account
  3. Collect information to get started:
            - Computer Name (remote computer)
            - Path and Name of the .DLL file
  4. Run the psexec.exe utility with the appropriate syntax...

To Register a "DllName.dll" file residing in the C:\Windows\System32
folder on "Computer1"...

Psexec \\Computer1 regsvr32 /s c:\windows\system32\dllname.dll

To Unregister the same .DLL file...

Psexec \\Computer1 regsvr32 /u /s c:\windows\system32\dllname.dll

Tuesday, September 1, 2009

The Tools at Your Disposal

When I was a sysadmin for a small company I used to get hit with a question quite a lot regarding “how do I…” with respect to automating things or making changes to all computers with least effort.  Microsoft gives us a plethora (I always wanted to use that word in a sentence) of tools and technologies for free, with which we can assemble our own solutions.  The best part of this approach is that not only is it all free, but they provide an insane amount of documentation, samples, and community support to help us understand it better, and solve our own problems.  Of course, Microsoft also sells solutions, but the real fun is building your own.

So, maybe you’re facing a question like this “how do I automatically map drives or printers for my users?” or “how do display a login banner?” or “how do I apply registry updates on computers?” and so forth.  But you don’t know which path to take which would address these questions with the least amount of effort and cost.  It all boils down to what operating systems and tools you have at hand…

Task XP/Vista
WorkGroup
XP
2K3 AD
Vista
2K3 AD
Vista
2K8 AD
Windows 7
2K8 AD
Map User Drives Script Script Script GP Prefs GP Prefs
Map Printers Script Script Script GP Prefs GP Prefs
Desktop Settings Local Policy GPO, Script GPO, Script GP Prefs GP Prefs
Registry Updates Script Script, GPO Script, GPO GP Prefs GP Prefs
Clone Registry Settings Script Script Script GP Prefs GP Prefs
File Cleanups Script Script Script Script Script
Create/Update Shared Folders Script Script Script GP Prefs GP Prefs
Create/Update Files Script Script Script GP Prefs GP Prefs
Create/Update INI Files Script Script Script GP Prefs GP Prefs
Create/Update Folders Script Script Script GP Prefs GP Prefs
Create/Update Shortcuts Script Script Script GP Prefs GP Prefs
Create/Update Env Vars Script Script Script GP Prefs GP Prefs
Create/Manage Power Plans Script Script, GPO Script, GPO GP Prefs GP Prefs
Create/Update Scheduled Tasks Script Script Script GP Prefs GP Prefs
Register File Types Script Script, GPO Script, GPO GP Prefs GP Prefs
Configure Network Settings Script Script Script GP Prefs GP Prefs
Automate VPN Configs Script Script, GPO Script, GPO GP Prefs GP Prefs
Create/Update DSNs Script Script, GPO Script, GPO GP Prefs GP Prefs
Create Local Users/Groups Script Script Script GP Prefs GP Prefs
Collect Inventory Data at Login or Startup Script Script Script Script Script
Customize IE Configuration Script GPO GPO GP Prefs GP Prefs
Customize Office Settings Script GPO GPO GPO/GP Prefs GPO/GP Prefs
Configure Regional Options Script GPO GPO GP Prefs GP Prefs
Configure Local Services Script GPO GPO GP Prefs GP Prefs
Install Apps from Network Shares Script Script Script GP Prefs GP Prefs
Configure Event Fwd-ing Script Script Script GPO GPO

Conclusion

If you have a Windows Server 2008 license in your environment, and at least some Vista or (maybe) Windows 7 clients, you’d be fool to ignore Group Policy Preferences.  The features are amazingly powerful and simple to use.  You can rip out tons of scripting and replace it with a few mouse clicks.  I’m a scripting NUT so if I say something like that it means a lot (to those unlucky enough to know me).  GP Prefs are also nowhere near as complex to learn and use as Group Policy settings.  If you have half of a brain you can figure it out without having to dig into any documentation at all.  It’s that easy.

Caveates and Disclaimers

This table is simply a “best option” recommendation from my own experience.  It is not something developed or condoned by Microsoft in any respect.  You may often find it necessary, even ideal, to mix scripting, GPO and Group Policy Preferences techniques to address your needs.  One solution is not likely going to fit all or even most of your needs.

Items marked with “Script” imply user permissions constraints for login scripts.  For startup scripts, you may encounter some complexity when making changes for specific user profiles, as opposed to the “all-users” profile.  Startup scripts which need to access resources over a network may require additional permissions settings on those remote resources in order to allow access.

Scripting capabilities will vary by language and component dependencies.  Most often KiXtart, VBScript, BAT/CMD or PowerShell. 

PowerShell is not ideally suited for login scripting by itself, however it can be employed along with other scripts to perform specialized tasks with great results.  PowerShell scripting requires all clients involved to have the minimum supported version of .NET framework installed.

To enjoy the comforts of Group Policy Preferences, you simply need to have at least one Windows Server 2008 domain controller in your AD environment.  You do not have to change over to “native” mode.  GP Prefs are built into Windows 7 but require a separate (and free) download and installation for Windows XP and Vista clients.  Settings which only apply to Vista or Windows 7 are completely ignored by Windows XP clients.

All of this can be replaced or extended with the use of infrastructure management tools like SMS, System Center Configuration Manager, and so on.

Tuesday, May 19, 2009

Why Break Your Own Registry, When You Can Break Someone Else's?

I've played around with creating, reading and deleting registry keys, subkeys and values on a local machine for years.  Nothing new to report that hasn't been reported to death, ad infinitum and ad nauseum for years.  Maybe even millennia?  So I got bored (a rarity in my busy life) and tinkered with remote registry destruction.  Ok, just kidding.  I do NOT condone or suggest destruction of anything beyond insects that invade your house or vehicle.  I had an ant infestation in my truck years ago, not fun.

While the last few posts have demonstrated an unsurprising similarity between VBScript, KiXtart and even PowerShell, this time around, each shows some interesting differences.  First up is the VBScript example:

Based on code from the following links:

http://www.activexperts.com/activmonitor/windowsmanagement/adminscripts/registry/
http://msdn.microsoft.com/en-us/library/aa393286(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa393297(VS.85).aspx

' VBScript Remote Registry
' Create keypath HKLM\SOFTWARE\ATestKey
' Create three subkeys, each with a different value

Const strComputer = "COMPUTERNAME"
Const strKeyPath = "SOFTWARE\ATestKey"
Const strValueName = "ValueName1"

' defined all just for convenience, only using HKLM
Const HKCR = &H80000000
Const HKCU = &H80000001
Const HKLM = &H80000002
Const HKU = &H80000003
Const HKCC = &H80000005
Const HKDD = &H80000006

Wscript.Echo "CONNECTING TO CLIENT: " & strComputer
Wscript.Echo
On Error Resume Next
Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\default:StdRegProv")

If err.Number <> 0 Then
Wscript.Echo "unable to connect to " & strComputer
Wscript.Quit(1)
End If

Wscript.Echo "ADDING KEYS AND VALUES..."

test = oReg.CreateKey(HKLM, strKeyPath)
RegResult test

test = oReg.SetStringValue(HKLM, strKeyPath, strValueName, "ValueName1")
RegResult test

test = oReg.CreateKey(HKLM, strKeyPath & "\Subkey1")
RegResult test

test = oReg.CreateKey(HKLM, strKeyPath & "\Subkey2")
RegResult test

test = oReg.CreateKey(HKLM, strKeyPath & "\Subkey3")
RegResult test

test = oReg.SetExpandedStringValue (HKLM, strKeyPath & "\Subkey1", "ValueName1", "%PATH%")
RegResult test

iValues = Array("string1", "string2")
test = oReg.SetMultiStringValue(HKLM, strKeyPath & "\Subkey3", "ValueName2", iValues)
RegResult test

test = oReg.SetDWORDValue(HKLM, strKeyPath & "\Subkey2", "ValueName1", 8)
RegResult test

uBinary = Array(1,2,3,4,5,6,7,8)
test = oReg.SetBinaryValue(HKLM, strKeyPath & "\Subkey3", "ValueName1", uBinary)
RegResult test

Wscript.Echo "DELETING KEYS AND VALUES..."

test = oReg.DeleteValue(HKLM, strKeyPath, "ValueName1")
RegResult test
test = oReg.DeleteValue(HKLM, strKeyPath & "\Subkey1", "ValueName1")
RegResult test
test = oReg.DeleteValue(HKLM, strKeyPath & "\Subkey2", "ValueName1")
RegResult test
test = oReg.DeleteValue(HKLM, strKeyPath & "\Subkey3", "ValueName1")
RegResult test
test = oReg.DeleteValue(HKLM, strKeyPath & "\Subkey3", "ValueName2")
RegResult test
test = oReg.DeleteKey(HKLM, strKeyPath & "\Subkey1")
RegResult test
test = oReg.DeleteKey(HKLM, strKeyPath & "\Subkey2")
RegResult test
test = oReg.DeleteKey(HKLM, strKeyPath & "\Subkey3")
RegResult test
test = oReg.DeleteKey(HKLM, strKeyPath)
RegResult test

Sub RegResult(v)
Select Case v
Case 2:
Wscript.Echo "registry update failed: object not found"
Case 0:
Wscript.Echo "registry update successful"
Case Else:
Wscript.Echo "registry update failed (test = " & v & ")"
End Select
End Sub


I apologize for the laborious use of capturing the return value and checking it for results, but I wanted to show that you can at least rudimentary checking of what happens at each step.  For a exhaustive list of WBEMerror enumerations, which are what the oReg object returns into the "test" variable, click here.  Good luck translating the integer returns from VBScript into values shown.  It's also interesting (to me anyway) that some of the enumerations don't show a Hex value, such as wbemErrOutOfDiskSpace



If you really don't care about error trapping, you could compact the above code significantly, but I would recommend trapping at least the minimal shown above.



I will post some horrible-looking KiXtart and PowerShell examples later.  Maybe a part 2 and part 3?  Family becons me to the dinner table.

Wednesday, May 13, 2009

Playing With Fire

That's usually the first thing anyone says to someone when they're answering the question: "What is the 'registry'?"  They say "it's an evil box of destruction that will destroy your computer and all of mankind.  You're playing with fire!"  Ok, I think I actually heard someone say that once.  It was probably me.

Today's walk down destruction lane will focus on the registry.  And because I try to make everyone happy (and end up making nobody happy as a result) will pain the picture with not one, not two, not even three, but FOUR languages!  Amazing!  How the *$(^^*#$ does he do that?!  Pssstt.  Come closer... I have to whisper this.... it's called... Google.

I've been writing scripts for almost 20 years in a variety of languages, but I still look for the easy way out.  That's what scripting is all about: saving time and saving work.  Programmers look to make something awe-inspiring.  Scripters look to make things that free them up to drink more beer and make jokes about programmers.  Scripters also get to the bar earlier and therefore finish off the snacks before the worn-out programmers show up.  You know: while you're compiling, I'm doing something more fun.

Enough of that gibberish.  It'll melt your mind.  Here are four ways to query a registry key and pull all the sub-keys and values beneath it.  They aren't all purely recursive.  Two of them are, two of them aren't.  The two that are can be considered completely cheating, but who cares.  The VBScript and KiXtart examples are one-deep, not exhaustively recursive.  The CMD and PowerShell examples are.  Let's start with the ugly first, but please read the comments at the end as well?

VBScript:

Option Explicit

' Adapted from ActiveXperts registry script library...
' Click Here

Const strComputer = "."

Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_USERS = &H80000003
Const REG_SZ = 1
Const REG_EXPAND_SZ = 2
Const REG_BINARY = 3
Const REG_DWORD = 4
Const REG_MULTI_SZ = 7

Dim StdOut, oReg
Set StdOut = WScript.StdOut

Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\default:StdRegProv")

EnumSubkeys HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services"

Sub EnumSubkeys(hive, parentkey)
Dim subkey, arrSubKeys
Wscript.Echo "PARENTKEY: " & parentkey
oReg.EnumKey hive, parentkey, arrSubKeys
For Each subkey In arrSubKeys
EnumValueTypes hive, parentkey & "\" & subkey
Next
End Sub

Sub EnumValueTypes(hive, strKeyPath)
Dim i, x, ValueName, arrValueNames, arrValueTypes, strValue, arrValues
Wscript.Echo "SUBKEY: " & strKeyPath
oReg.EnumValues hive, strKeyPath, arrValueNames, arrValueTypes
If VarType(arrValueNames) > 8192 Then
For i=0 To UBound(arrValueNames)
ValueName = arrValueNames(i)
Wscript.Echo vbTab & "Value Name.: " & ValueName
Select Case arrValueTypes(i)
Case REG_SZ
Wscript.Echo vbTab & "Data Type..: REG_SZ"
oReg.GetStringValue hive, strKeyPath, ValueName, strValue
Wscript.Echo vbTab & "Value......: " & strValue
Wscript.Echo
Case REG_EXPAND_SZ
Wscript.Echo vbTab & "Data Type..: REG_EXPAND_SZ"
oReg.GetExpandedStringValue hive, strKeyPath, ValueName, strValue
Wscript.Echo vbTab & "Value......: " & strValue
Wscript.Echo
Case REG_BINARY
Wscript.Echo vbTab & "Data Type..: REG_BINARY"
oReg.GetBinaryValue hive, strKeyPath, ValueName, strValue
If VarType(strValue) > 8192 Then
For x = 0 to UBound(strValue)
Wscript.Echo vbTab & "Value......: " & strValue(x)
Next
End If
Wscript.Echo
Case REG_DWORD
Wscript.Echo vbTab & "Data Type..: REG_DWORD"
oReg.GetDWordValue hive, strKeyPath, ValueName, strValue
Wscript.Echo vbTab & "Value......: " & strValue
Wscript.Echo
Case REG_MULTI_SZ
Wscript.Echo vbTab & "Data Type..: REG_MULTI_SZ"
oReg.GetMultiStringValue hive, strKeyPath, ValueName, arrValues
For each strValue in arrValues
Wscript.Echo vbTab & "Value......: " & strValue
Next
Wscript.Echo
End Select
Next
Else
Wscript.Echo vbTab & "Data Type..: " & VarType(arrValueNames)
End If
End Sub




KiXtart:





; Adapted from fEnumKey() by Howard A. Bullock
; Click Here

Break ON

$regkey = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services"
$=EnumSubkeys($regkey)

Function EnumSubkeys($parentkey)
Dim $index, $error, $x
$index = 0
Dim $keyname[$index]

If KeyExist($parentkey)
Do
$x = EnumKey($parentkey, $index)
$error = @error
If Not $error And $index > Ubound($keyname)
ReDim Preserve $keyname[$index]
EndIf
If Not $error
$keyname[$index] = $x
$index = $index + 1
$=EnumKeyValues("$parentkey\$x")
EndIf
Until $error
Else
$keyname[0] = ""
Exit 2
EndIf
EndFunction

Function EnumKeyValues($subkey)
Dim $i, $valuename, $v, $vname, $rval, $rtyp
$i = 0
Dim $vname[$i]
? "SUBKEY: $subkey"
Do
$v = EnumValue($subkey, $i)
$err = @error
If Not $err And $i > Ubound($vname)
ReDim Preserve $vname[$i]
EndIf
If Not $err
$vname[$i] = $v
$rval = ReadValue($subkey, $v)
$rtyp = ReadType($subkey, $v)
$i = $i + 1
? Chr(9)+"ValueName..: $v"
? Chr(9)+"Value......: $rval"
? Chr(9)+"Data Type..: $rtyp"
?
EndIf
Until $err
EndFunction




PowerShell:





dir hklm:system\currentcontrolset\services -recurse -ea silentlycontinue




CMD Shell:





reg query HKLM\SYSTEM\CurrentControlSet\Services /s 



Comments:

You might have noticed that the last two examples are just a teensy-weensy bit shorter than the first two.  Just a little.  That's not really a fair comparison.  Comparing the brevity of languages is a slippery slope.  Because they can be described as smoke-and-mirrors in some respects.  Each "language" (or "engine" if you will) comes with a particular (singular or community based) mindset regarding what belongs in the "core" versus what should be left to YOU to add-on.



PowerShell derives much of its potential from cmdlets, which are modular functions which collectively fill-out the PowerShell capability set.  You could do very similar things with KiXtart UDF's (User Defined Functions), which are identical in many respects.  The difference beneath that layer is that PowerShell derives from the .NET services layer, while KiXtart derives from an aggregate of COM and WMI interfaces.  The results almost identical in most respects, but there is only major difference overall: KiXtart is procedural, while PowerShell is object-oriented.  Does that mean that KiXtart is *always* procedural and PowerShell is *always* object oriented?  No.  Cars aren't always cars either.



So, basically, essentially, in other words, and so on, you could produce an almost identical functional expression with KiXtart that you see with PowerShell by simply building (or downloading) a UDF and it would (or could) be as brief and simple.  The REG.EXE command (CMD Shell example) is a compiled, single-purpose executable, rather than a scripting engine or environment.  I included it simply to show that PowerShell is but one way to screw up your registry with the fewest keystrokes.  (A dangerous combination if you drink beer AND a Red Bull in the same hour as you start playing with that.)



As I mentioned in an earlier post, there are trade-offs to each and every "tool" you use.  Some will be faster and easier at some things, but harder to lug around.  A good example of this is CMD shell, which is already pervasive, versus PowerShell, which is still in its infancy of pervasiveness.  Then there's KiXtart which is like a suitcase with a nuclear bomb in it.  Powerful, yet completely portable and fairly lightweight.  PowerShell on the other hand is not lightweight, and requires not only .NET Framework, but it's own installation, in order to crank it up and start using it.  But once it's roots are planted, it rocks.



Well, the goal of this article was to show some simple comparisons and discuss some of the differences between them.  I hope this helps!  Cheers!