Trigger a hardware detection scan from Delphi, InstallShield, C++, script or Run prompt
January 4, 2007
In my deployment process, it had looked like I was going to need to detect some changes in hardware and then perform a reboot.
I researched how to do this but it turns ou that I don’t need this code. Into the cave it goes.
You can of course run the “Add New Hardware” wizard manually. Here’s the command line to do just that:
“C:\WINDOWS\system32\rundll32.exe” C:\WINDOWS\system32\shell32.dll,Control_RunDLL “C:\WINDOWS\system32\hdwwiz.cpl”,Detect Hardware
However, what if you want to automate the process.
The information for how to do this is relatively scarce even though there is a technet page about it. Strangely enough the first thing I found was an NSIS script for doing this through that open source instalation program. The strange thing about it is that it was on a WinAMP website (link).
Here’s that code:
[code]
Function ScanForNewHW
SetPluginUnload alwaysoff
StrCpy $1 ""
System::Call 'setupapi::CM_Locate_DevNodeA(*i .r0, t r1, i r2) i .r3'
System::Call 'setupapi::CM_Reenumerate_DevNode(i r0, i r4) i .r5'
SetPluginUnload manual
System::Free 0
FunctionEnd
[/code]
Armed with the DLL name, the second thing I found was an Install Shield script (link) that allowed it to be done:
[code]
function ScanForHardwareChanges()
NUMBER devInst, myreturn;
begin
if(UseDLL(WINSYSDIR ^ "cfgmgr32.dll") != 0)then
MessageBox("Didn't load Dll", SEVERE);
return FALSE;
endif;
myreturn = CM_Locate_DevNodeA(&devInst, "\0", 0);
myreturn = CM_Reenumerate_DevNode(devInst, 0);
UnUseDLL(WINSYSDIR ^ "cfgmgr32.dll");
return TRUE;
end;
[/code]
Armed with the DLL name and a possible procedure name, I was able to track down the Microsoft support page about it (link). That page provided a C routine for calling the code. Here it is:
[C]
BOOL ScanForHardwareChanges()
{
DEVINST devInst;
CONFIGRET status;
//
// Get the root devnode.
//
status = CM_Locate_DevNode(&devInst, NULL, CM_LOCATE_DEVNODE_NORMAL);
if (status != CR_SUCCESS) {
printf(“CM_Locate_DevNode failed: %x\n”, status);
return FALSE;
}
status = CM_Reenumerate_DevNode(devInst, 0);
if (status != CR_SUCCESS) {
printf(“CM_Reenumerate_DevNode failed: %x\n”, status));
return FALSE;
}
return TRUE;
}
[/c]
However, I wanted to do this in Delphi. With the correct constant names, I was able to find two references to this routine. The Delphi JEDI project has a provides a routine for loading the DLL that allows these calls to be made and either someone (link) translated Microsoft’s code into a routine for scanning for the hardware or there was a, now gone, JEDI demo project that included this routine. Either way, the French site was the first one I’d found that scanned for new hardware with Delphi.
Here is that code:
[delphi]
procedure SomeProcedure;
// First you need to load the module.
LoadConfigManagerApi;
// Then call a translation of the MS routine
ScanForHardwareChanges;
end;
// Here’s the translation of the ScanForHardwareChanges
function ScanForHardwareChanges: boolean;
var
dev: DEVINST;
status: CONFIGRET;
begin
status := CM_Locate_DevNode(dev, ”, CM_LOCATE_DEVNODE_NORMAL);
if (status <> CR_SUCCESS) then
begin
result := FALSE;
exit;
end;
status := CM_Reenumerate_DevNode(dev, 0);
if (status <> CR_SUCCESS) then
begin
result := FALSE;
exit;
end;
Result := TRUE;
end;
[/delphi]
That routine was picked up on a Russian site (link) and modified to be independent of the JEDI files. However, both of these routines include way more information than is needed.
The process is really simple.
1. Load the DLL
2. Get the location of the two methods you need.
3. Call them (using the appropriate constants
4. Unload everything.
I’ve written my own Delphi routine that does all that and has no extra baggage dragged (drug?) along for the ride..
My all-in-one solution:
[delphi]
{******************************************************************************
ScanForHardwareChanges
by Brian Layman at TheCodeCave.com
******************************************************************************}
function ScanForHardwareChanges: Boolean;
const
CFGMGR32_DLL = ‘cfgmgr32.dll’;
CM_LOCATE_DEVNODE_NAME = ‘CM_Locate_DevNodeA’;
CM_REENUMERATE_DEVNODE_NAME = ‘CM_Reenumerate_DevNode’;
CM_LOCATE_DEVNODE_NORMAL = $00000000;
CR_SUCCESS = $00000000;
var
DeviceNode: DWord;
HCfgMgr: THandle;
CM_Locate_DevNode: function(var dnDevInst: DWord; pDeviceID: PAnsiChar;
ulFlags: ULONG): DWord; stdcall;
CM_Reenumerate_DevNode: function(dnDevInst: DWord; ulFlags: ULong): DWord; stdcall;
begin // ScanForHardwareChanges
Result := FALSE;
HCfgMgr := LoadLibrary(CFGMGR32_DLL);
if (HCfgMgr < 32)
then MessageDlg('Error: could not find Configuration Manager DLL', mtError, [mbOk], 0)
else begin
try
CM_Locate_DevNode := GetProcAddress(HCfgMgr, CM_LOCATE_DEVNODE_NAME);
CM_Reenumerate_DevNode := GetProcAddress(HCfgMgr, CM_REENUMERATE_DEVNODE_NAME);
if (CM_Locate_DevNode(DeviceNode, NIL, CM_LOCATE_DEVNODE_NORMAL) = CR_SUCCESS)
then Result := (CM_Reenumerate_DevNode(DeviceNode, 0) = CR_SUCCESS);
finally // wrap up
FreeLibrary(HCfgMgr);
end; // try/finally
end;
end; // ScanForHardwareChanges
[/delphi]
As a bonus, here it is combined into a project that scans for new hardware and then reboots the computer.
Read more
Copy To Clipboard in HTML
June 2, 2006
or Speed blogging Exposed…
or “Copy as Text Link” and “Copy as Image Link” Blogging Tools explained.
Usually when I post something technical, I include a detailed
The batch file did the following neat stuff…
1. Used Environmental variables to create HTML files in a standard Windows directory
2. Dynamically add string and DWord registry entries
3. Demonstrated adding menu items to Maxthon & Internet Explorer (Unfortunatly these do not show up in FF or Opera.)
4. Displayed different contexts based upon what was selected.
5. Launched another IE window that does not effect the output but does process information selected in the first.
6. Demonstrated how to copy HTML source to the paste buffer via HTML and javascript.:
7. Copied text to the clipboard, formatting it into HTML
Not bad for a small batch file.
So, here’s how the magic was done…
First, the easy stuff. The batch file creates two text files. That is done using the redirection symbol (aka the output to file symbol) which is > (aka the Greater Than sign). The Greater than sign appends the displayed results directly to a file. Two greater thans in a row cause the file to be recreated. I use the Echo command to echo (go figure) text to two HTML files I will be creating. Since I use >> in the first line, those files will always be recreated if the batch file is run again.
Because HTML also uses GT and LT symbols, they must be denoted as literal symbols. That is done with the carot symbol ^. Thusly
[dos]
echo ^>%windir%\web\copytextaslink.htm
echo ^
[/js]
As you can see, the bulk of the file is JavaScript. The second line clearly declares it so. However, instead of putting Language=”JavaScript” (which is the old school way of doing things and how I learned originally), I should have specified it as a MIME type like this Type=”text/javascript” The end result is the same, however eventually the old language option will be dropped.
Another option that you might not be familiar with is the defer flag. This is a browser load time optimizer. It tells the browser that the contents of the script will not effect the layout of the page and therefore the browser can continue drawing the page.
The process is also pretty easy to follow because it uses Microsoft’s DOM technology. DOM is the Document Object Module and allows IE to handle all web pages as if it were Object Oriented. You can reference the document and the various parts/divisions of any web page. And that allows you to directly access properties or methods of these objects.
So what the code above does is asks for the document in the parent window (the one in which you right clicked). It then asks for the current selection (if any). It then gets the current selection as text and then asks for the clibboard object for the current window. At that point it is a simple call to SetData and the selected text is added (with a few additions) to the clippboard. There isn’t much more than that. One thing that should be noted is that the type of data in the clibboard must be specified, in this case, as text. You can read more about the other types of data that a clib board can handle in my article about Clipboard manipulation with Delphi HERE:
The second file proceeds much the same way except that it goes further into the DOM and retreives the Height and Width of the original image so that the pasting of the tag in your blog can include that information (most specifically, the aspect ratio.
[js]
[/js]
That’s it for the HTML. The only thing left is to create a couple of triggers to activate those two files. That’s done through the registry.
Internet explorer reads through the registry each time it pops up a menu. It first decides what is clicked and then looks at the registry entries under HKey_CurrentUser\Software\Microsoft\Internet Explorer\MenuExt\ all of the menu items that match the type of selection. MSDN has a full article that explains this in detail HERE, however, the following table is probably all you’ll need:
| Context | Value |
|---|---|
| Default | 0×1 |
| Images | 0×2 |
| Controls | 0×4 |
| Tables | 0×8 |
| Text selection | 0×10 |
| Anchor | 0×20 |
So, the last step of the process is to route the text to the text processing HTML and the img tag source to the image text file.
That’s done in these two lines…
[dos]
reg ADD “HKCU\Software\Microsoft\Internet Explorer\MenuExt\Copy Image as Lin&k” /ve /t REG_SZ /d “%WINDIR%\web\copyimageaslink.htm” /f
reg ADD “HKCU\Software\Microsoft\Internet Explorer\MenuExt\Copy Image as Lin&k” /v Contexts /t REG_DWORD /d 2 /f
.
[/dos]
That’s it! You’ve got your full walk through! Any questions?
“Copy as Text Link” and “Copy as Image Link” Blogging Tools
May 26, 2006
Justin of JustInsomnia had a great idea for a FireFox plug in:
I want to be able to copy a quote and its URL at the same time, without having to so much as think about it. To do so, I wrote my first Firefox extension, which I opted to name the somewhat homely, Copy as HTML Link.
So he created Copy as HTML Link for Firefox and generously shared his moment with wp-hackers Subscribers .
The plugin looks good and he did a really good job documenting it (THIS IS RARE!):
I must say that since I’ve started using this method, it’s been a quite a time saver. This was a GREAT idea. Inspired! So, if you have FireFox, please head on over there and get that plug-in!
Ah, but here’s the fly in the ointment and the sand in my… socks: A Firefox plugin won’t work for Maxthon!!!! (
) or Internet Explorer!
You see, Firefox just doesn’t do it for me.
Opera comes darn close to being right, but I like the extra usability features in Maxthon.
So, I thought… Hey… I could do that for Maxthon and IE AND I could do it all from a BATCH file!
So, here it is…
Run this Batch file and you will have installed on your system, two new menu items. When you highlight text, you’ll have an option to “Copy as Link” and when an image is right clicked, you will get an option to “Copy Image as Link”. Hopefully I’ve chosen hotkeys that will work well for you… If not, you can change them in RegEdit at HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\
BTW EVERY image and link up to this point in this post was created using this tool. Man, Good idea Justin!
Also – If you find that IE is prompting you asking for permissions to open the links, please post a comment and I’ll show how to fix that. I’ve gotten that message on other things I’ve like this I’ve created and know how to get past it. I’ve disabled that workaround on this computer and I am not getting that “Are you sure” message. So these menu items should be safe. ALSO, some popup blockers may block these items. You might have to add localhost as a site that is allowed to show popups in your particular popup blocker. Let me know if you have any problems.
Here’s the download: http://www.TheCodeCave.com/downloads/batch/AddCopyAsLink.bat
Here is the source:
[DOS]
@echo Off
:: Implements “Copy * as Link” menu items in IE and Maxthon
:: Written by Brian Layman
:: Visit me at: http://www.TheCodeCave.com
:: Version 0.1
:: Update Url: http://www.thecodecave.com/?p=152
:: Inspired by Justin’s Firefox Plubin
:: Found at: http://justinsomnia.org/2006/05/copy-as-html-link-for-firefox/
:: Create file for the Copy Text as Link
echo ^>%windir%\web\copytextaslink.htm
echo ^>>%windir%\web\copytextaslink.htm
echo ^
