How do I find DOMAIN\accountname$ of a remote AD-joined computer? - windows

I want to store a remote computer's account name in a variable in the DOMAIN\Accountname format (preferably DOMAIN\Accountname$. I know the DNS name and samaccountname of the computer, and I want to run the script on a domain-joined computer (not a domain controller).
I cannot find any simple one-line approach to get the account name in that format. I can manually construct the string by concatenating the NETBIOS domain name with computer name (samaccountname), but I was assuming there is an easier and more robust way of doing this.
So is there any built-in approach of getting the computer name in the DOMAIN\Accountname$ format without having to manually constructing the string? I assume that's common task.

You can also look at the environmental variables. For this question, I would do the following...
$strUserAndDomain = ((Get-Content env:userdomain) + "\" + (Get-Content env:username))
Then you can user the value of $strUserAndDomain whenever you want.

Related

How do you find the correct verb names to use with FolderItem.InvokeVerb?

How does one find the exact verbs to be used with the Windows API function FolderItem.InvokeVerb? The documentation says, "It must be one of the values returned by the item's FolderItemVerb.Name property." However, this does not seem to be true.
Using a folder as an example, if you run this on Windows 10 (using PowerShell):
$Shell = New-Object -ComObject 'Shell.Application'
$Shell.NameSpace('C:\Windows').Self.Verbs()
you will get a list that looks like this:
Application Parent Name
----------- ------ ----
&Open
Pin to Quick access
Scan with Microsoft Defender...
... and so on.
Those Names are what you get in an Explorer context menu, but they do not work with InvokeVerb. For some of them, such as &Open, all you have to do is remove the &. For others, such as Pin to Quick access, the actual verb that works is altogether different (pintohome). How can one reliably find these "actual" verbs for an arbitrary item?
I have found that the verbs that do work with InvokeVerb correspond to the sub-keys that you can find in the Registry under HKCR\<class name>\shell. However, even knowing that does not make things simple. I have found some verbs before by searching HKCR for the string returned by FolderItemVerb.Name, but that doesn't work if the string is localized. If you happen to know the name of the class, you could look there directly. (Using the folder example, pintohome is one of the keys under HKCR\Folder\shell.) However, when it is localized, there is nothing there that directly indicates this is the verb you are looking for, so you have to try it to find out. And, if you are inside some special shell folder or namespace extension, you might not know what class name(s) to even go looking for.

What's the Hash in HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.<extension>\UserChoice?

With Windows 8, the user's choice for which application to open for a given document type seems to be kept in
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\<extension>\UserChoice
For PDFs on my machine, this contains:
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pdf\UserChoice]
"Hash"="xh8KhPWlZL0="
"ProgId"="AcroExch.Document"
Yet on another machine the hash is different. What's being hashed, and is there any way to create a .reg file which can be applied to another machine to set this preference?
Someone reverse engineered the hash and wrote a CLI tool to set file associations:
http://kolbi.cz/blog/?p=346
extension = “.txt”; the file extension
sid = “S-1-5-21-463486358-3398762107-1964875780-1001” ; the SID of the current user
progid = “txtfile”; the ProgId of the desired association
regdate = “01d3442a29887400”; timestamp of the UserChoice registry key
experience = “a microsoft secret string”; a static string (this is a dummy example, not the real string
hash = Base64(MicrosoftHash(MD5(toLower(extension, sid, progid, regdate, experience))))
Not all details are revealed but probably enough to reverse engineer the rest.
Microsoft decided in Windows 8 (probably for security reasons) that users should be able to set default programs only via the built in GUI. I.e. by design, you are not supposed to be able to set default handlers in a script or programmatically.
The Hash value is used to prove that the UserChoice ProgId value was set by the user, and not by any other means. This works as long as Microsoft keeps the algorithm which generates the Hash, and the mechanism for verifying the ProgId using the Hash, a secret.
In theory you could figure out the secret to set the Hash (and possibly other hidden OS settings), but you would have no guarantee of it's reliability; the next Windows Update might break your method, for example. You probably just need to adapt to the change, and live with using the new methods Microsoft built in to the OS.
By the way, these userchoice hashes in a profile become invalid after a sysprep, causing all those "an app default was reset" messages during the first login after sysprep, and many log entries in Microsoft-Windows-Shell-Core/AppDefaults.

Creating a registry key with path components via PowerShell

For a legacy application, I need to create a registry key with a name in the format c:/foo/bar/baz. (Note: forward slashes, not backslashes.) To be clear: that is a single key's name, with forward slashes, that otherwise looks like a Windows path. Because I need to script this against lots of servers, PowerShell seems like a great option.
The problem is that I cannot figure out how to create a key in that format via PowerShell. New-Item -Path HKLM:\SOFTWARE\Some\Key -Name 'c:/foo/bar/baz' errors out with PowerShell thinking I'm using / as a path separator and failing to find the path HKLM:\Software\Some\Key\c:\foo\bar, which does indeed not exist (and shouldn't). I can't find any other way to (ab)use New-Item to get what I want.
Is there something I'm missing, or should I give up and just generate and load a registry dump the old-fashioned way?
You need to do two things. First you need to get a writable RegistryKey object, otherwise you can't modify anything anyway. Second, use the CreateSubKey method on the RegistryKey object directly.
$writable = $true
$key = (get-item HKLM:\).OpenSubKey("SOFTWARE", $writable).CreateSubKey("C:/test")
$key.SetValue("Item 1", "Value 1")
After you create the key you use the resulting object to add values to it.

script to map networkdrive base on username

I have a .cmd script I want to map a network drive based on the username of the person running it. So something like this
net use K: \\nas001\users\[My_User_Name]
Except replace [My_User_name] with the name of the user running the script. Is this possible?
The environment variable %USERNAME% contains the actual user name, so you could use this, but I wouldn't advice this.
Windows has the concept op 'home drive', to which you can connect using:
NET USE K: /HOME
I think it's better to use that concept.

How do I resolve a canonical filename in Windows?

If I have a string that resolves to a file path in Windows, is there an accepted way to get a canonical form of the file name?
For example, I'd like to know whether
C:\stuff\things\etc\misc\whatever.txt
and
C:\stuff\things\etc\misc\other\..\whatever.txt
actually point to the same file or not, and store the canonical form of the path in my application.
Note that simple string comparisons won't work, nor will any RegEx magic. Remember that we have things like NTFS reparse points to deal with since Windows 2000 and the new Libraries structure in Windows 7.
Short answer: not really.
There is no simple way to get the canonical name of a file on Windows. Local files can be available via reparse points, via SUBST. Do you want to deal with NTFS junctions? Windows shortcuts? What about \\?\-escaped filenames
Remote files can be available via mapped drive letter or via UNC. Is that the UNC to the origin server? Are you using DFS? Is the server using reparse points, etc.? Is the server available by more than one name? What about the IP address? Does it have more than one IP address?
So, if you're looking for something like the inode number on Windows, it ain't there. See, for example, this page.
Roger is correct, there is no simple way. If the volume supports file a unique file index, you can open the file and call GetFileInformationByHandle, but this will not work on all volumes.
The Windows API call GetFullPathName may be the best simple approach.
GetFinalPathNameByHandle appears to do what your asking for, which is available starting with Windows Vista.
Using FileInfo (example in C#):
FileInfo info1 = new FileInfo(#"C:\stuff\things\etc\misc\whatever.txt");
FileInfo info2 = new FileInfo(#"C:\stuff\things\etc\misc\other\..\whatever.txt");
if (info1.FullName.Equals(info2.FullName)) {
Console.WriteLine("yep, they're equal");
}
Console.WriteLine(info1.FullName);
Console.WriteLine(info2.FullName);
Output is:
yep, they're equal
C:\stuff\things\etc\misc\whatever.txt
C:\stuff\things\etc\misc\whatever.txt
jheddings has a nice answer, but since you didn't indicate which language you are using, I thought I'd give a Python way to do it that also works from the command line, using os.path.abspath:
> python -c "import os.path; print os.path.abspath('C:\stuff\things\etc\misc\other\..\whatever.txt')"
C:\stuff\things\etc\misc\whatever.txt
I would use System.IO.Path.GetFullPath. It takes a string as an input (C:\stuff\things\etc\misc\other..\whatever.txt in your case) and will output a string (C:\stuff\things\etc\misc\whatever.txt).
I guess I'm a little late, but you can use System.IO.Path.GetFullPath("C:\stuff\things\etc\misc\other..\whatever.txt") and it will return "C:\stuff\things\etc\misc\whatever.txt"
To get canonical path you should use PathCanonicalize function.

Resources