![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
|
Welcome to Vista Forums we are your forum to discuss Windows Vista x64 and x86 systems. Whether you need help or just want to post an idea you have on Vista, this is the forum for you.
br> br> |
| |||||||
![]() |
| | Thread Tools | Display Modes |
| | #1 (permalink) |
| Guest | Cmdlet Parameter Binding Question With my Get-Hash cmdlet I have a string[] Path property that can be bound to the pipeline allowing me to use the cmdlet like this: dir *.exe | get-hash However this seems to preclude me from doing this: "c:\boot.ini" | get-hash Where I want to hash the string and not the file c:\boot.ini. Is this just a case of you can't have your cake and eat it too? Is there a way to force the string to bind to the "Object" parameterset instead of the "Path" parameterset? BTW trying to do what I want here probably isn't a good idea because it requires me to pick an Encoder to convert the string to a byte[] for hashing. That presumes I can easily find out the encoding a string which I can't. Does someone know of a .NET framework trick to figure this out? IIRC this is a fundamentally difficult problem. Save the string " abc.bak abc.txt" without the quotes in notepad sometime (use ASCII encoding) and then reload it. Interesting. Raymond Chen has a nice write-up on this at: http://blogs.msdn.com/oldnewthing/ar.../24/95235.aspx -- Keith |
My System Specs![]() |
| | #2 (permalink) |
| Guest | Re: Cmdlet Parameter Binding Question Hi Keith, > BTW trying to do what I want here probably isn't a good idea because it > requires me to pick an Encoder to convert the string to a byte[] for > hashing. That presumes I can easily find out the encoding a string which I > can't. Does someone know of a .NET framework trick to figure this out? In .NET a string is _always_ Unicode. It's not possible to say this string should be ASCII and that UTF8 or the like. It's up to you to load the right bits into the string by using the appropriate Encoding when opening a file or using Encoding.GetChars. But once it's loaded the string is treated as Unicode. So it doesn't make sense to ask what encoding a string has - it's Unicode. So this leads to the question of how to figure out the encoding of a file. Well, if it does not have a BOM you are lost. Regardless of how smart an algorithm for automatically figuring out a files encoding is, at the end this algorithm must guess. So when it comes to calculate the Hash you should always treat a file as a binary. If you get a string then this string is unicode, period. If one wants the hash of a ASCII or whatever string then the _caller_ must provide the appropriate byte representation and pass it as a byte array, because only the caller knows what he wants. hth Max |
My System Specs![]() |
| | #3 (permalink) |
| Guest | Re: Cmdlet Parameter Binding Question "Maximilian Hänel" <ngSpam@smjh.de> wrote in message news:%23SOG4x4GHHA.1276@TK2MSFTNGP04.phx.gbl... > So when it comes to calculate the Hash you should always treat a file as > a binary. If you get a string then this string is unicode, period. If > one wants the hash of a ASCII or whatever string then the _caller_ must > provide the appropriate byte representation and pass it as a byte array, > because only the caller knows what he wants. Re .NET strings and encoding, doh! That was a sleep deprivation induced brain fart. :-( So string would be nice to be nice accept as pipeline input except that my Path parameter is of type string[] so that someone can pass in a string that is a path to a file to hash. Because the type is string it gets mapped to the Path parameter. This is how the various *-item cmdlets work. You can pass them a FileInfo, any object with a Path/PSPath property or a *string* path via the pipeline. In general I think it is useful to be able to operate on files via a string path, say perhaps you have a file containing a list of paths to get hashes of. Of course, you can bypass the parameter/type mapping by using -InputObject. Does this seem like a reasonable way to operate directly on strings? 2> "abcdefghijklmnopqrstuvwxyz" | get-hash -InputObject {$_} Path : Algorithm : MD5 HashString : 35020D67A52D8E915330F0A77F676BBF Hash : {53, 2, 13, 103, 165, 45, 142, 145, 83, 48, 240, 167, 127, 103, 10 7, 191} I guess it depends on whether it is going to be more common for folks to want to hash files or strings. Opinions? -- Keith |
My System Specs![]() |
| | #4 (permalink) |
| Guest | Re: Cmdlet Parameter Binding Question Keith Hill [MVP] wrote: > Does this seem like a reasonable way to operate directly on strings? > > 2> "abcdefghijklmnopqrstuvwxyz" | get-hash -InputObject {$_} Does this not work? get-hash -InputObject "abcdefghijklmnopqrstuvwxyz" I think hashing strings could be useful, but the most common case will be hashing files. I think: get-hash "foo" should hash a file named foo get-hash -InputObject "foo" should hash the string foo "foo" | get-hash ... I'm not 100% sure, but I think it should also hash the string "foo", if that's possible to do... And regarding hashing strings, I'll make a small clarification. Max wrote "So it doesn't make sense to ask what encoding a string has - it's Unicode." Actually, .NET strings do have an encoding, which is UCS-2 (system-endian). This makes it a bit tricky if you want to hash them, because the string's raw stream of bytes is different on little-endian and big-endian systems. I guess I would recommend that you allow the user to override the encoding, but choose a default, like little-endian UCS-2 (which corresponds to Encoding.Unicode) when you convert the string to bytes. |
My System Specs![]() |
| | #5 (permalink) |
| Guest | Re: Cmdlet Parameter Binding Question Adam Milazzo wrote: > I guess I would recommend that you allow the user to override the > encoding, but choose a default, like little-endian UCS-2 (which > corresponds to Encoding.Unicode) when you convert the string to bytes. Correction, apparently Encoding.Unicode is little-endian UTF-16, not little-endian UCS-2. Although .NET strings are still stored in memory as system-endian UCS-2, as I said. So there's probably no way to get the little-endian UCS-2 bytes except to do it yourself. It's not too hard: byte[] bytes = new byte[str.Length*2]; for(int i=0,j=0; i<str.Length; j+=2,i++) { char c = str[i]; bytes[j] = (byte)(c&0xFF); bytes[j+1] = (byte)(c>>8); } This should work correctly on little-endian systems. For big-endian systems, just swap "c&0xFF" and "c>>8". You can determine the current endianness using BitConverter.IsLittleEndian. Then again, you might just use Encoding.Unicode as the default anyway and forget about UCS-2. I guess it doesn't really matter what you use as the default, as long as it has a fixed endian-ness so the hash is the same on big-endian and little-endian machines... |
My System Specs![]() |
| | #6 (permalink) |
| Guest | Re: Cmdlet Parameter Binding Question "Adam Milazzo" <adamm@san.rr.com> wrote in message news:%23d7OYlBHHHA.1264@TK2MSFTNGP03.phx.gbl... > Keith Hill [MVP] wrote: >> Does this seem like a reasonable way to operate directly on strings? >> 2> "abcdefghijklmnopqrstuvwxyz" | get-hash -InputObject {$_} > > Does this not work? > > get-hash -InputObject "abcdefghijklmnopqrstuvwxyz" > Yeah that is the way to do it. No obvious but not hard either. > "foo" | get-hash ... I'm not 100% sure, but I think it should also hash > the string "foo", if that's possible to do... That's not easy because the -Path parameter is type string[] and PoSh helpfully takes that input and populates the Path property. -- Keith |
My System Specs![]() |
| | #7 (permalink) |
| Guest | Re: Cmdlet Parameter Binding Question "Keith Hill [MVP]" <r_keith_hill@mailhot.moc.nospam> wrote in message news:%232v0O%233GHHA.1240@TK2MSFTNGP03.phx.gbl... > With my Get-Hash cmdlet I have a string[] Path property that can be bound > to the pipeline allowing me to use the cmdlet like this: > > dir *.exe | get-hash > > However this seems to preclude me from doing this: > > "c:\boot.ini" | get-hash > > Where I want to hash the string and not the file c:\boot.ini. Is this > just a case of you can't have your cake and eat it too? Is there a way to > force the string to bind to the "Object" parameterset instead of the > "Path" parameterset? Disclaimer: I am not a developer (well, I used to but that was pre-history) and I never tried to write any cmdlet. dir *.exe | get-member .... returns [System.IO.FileInfo] objects. So, why don't you create two parameter sets in your cmdlet? One would accept a [System.IO.FileInfo][] property to handle files and the other would accept a [System.String][] property to handle strings. Jacques |
My System Specs![]() |
| | #8 (permalink) |
| Guest | Re: Cmdlet Parameter Binding Question "Jacques Barathon [MS]" <jbaratho@online.microsoft.com> wrote in message news:emWwvdCHHHA.4116@TK2MSFTNGP05.phx.gbl... <...> > So, why don't you create two parameter sets in your cmdlet? One would > accept a [System.IO.FileInfo][] property to handle files and the other > would accept a [System.String][] property to handle strings. Very basic implementation in a filter (functions, filters and scripts don't implement parameter sets but they can verify their parameter types so that we can sort of emulate the functionality): PS> filter test-hash { >> if ($_ -is [System.IO.FileInfo]) {"Handling $_ as a file..."} >> else {if ($_ -is [System.String]) {"Handling $_ as a string..."}} >> } >> PS> "hello"|test-hash Handling hello as a string... PS> dir *.exe|test-hash Handling C:\Users\jbaratho\Documents\Private\test\notepad.exe as a file... Handling C:\Users\jbaratho\Documents\Private\test\regedit.exe as a file... Handling C:\Users\jbaratho\Documents\Private\test\sid2name.exe as a file... Jacques |
My System Specs![]() |
| | #9 (permalink) |
| Guest | Re: Cmdlet Parameter Binding Question Hi Adam, > So there's probably no way to get the little-endian UCS-2 bytes except > to do it yourself. It's not too hard: But does it make sense to calculate a strings hashcode platform dependend? At least to me it makes much more sense to calculate the hashcode of a .NET string in a consistent manner. So it's probably better to use Encoding.Unicode.GetBytes() for the hash calculation. As I already mentioned: If one wants the hashcode of a different byte representation then the caller should provide that byte sequence. > Then again, you might just use Encoding.Unicode as the default anyway > and forget about UCS-2. I guess it doesn't really matter what you use as > the default, as long as it has a fixed endian-ness so the hash is the > same on big-endian and little-endian machines... Ok, I should first read the full posting before writing any comments ;-) cu Max |
My System Specs![]() |
| | #10 (permalink) |
| Guest | Re: Cmdlet Parameter Binding Question Hi Keith, > Of course, you can bypass the parameter/type mapping by using > -InputObject. Does this seem like a reasonable way to operate directly > on strings? > > 2> "abcdefghijklmnopqrstuvwxyz" | get-hash -InputObject {$_} I like this idea and it's also very consistent with other CmdLets. Just take a look at the Select-String CmdLet. A string is always treated as a path as long as you don't tag it as an InputObject. The nice thing about this is, that one could then write: PS > Get-Hash *.ps1,*.cs | Select HashString, Path | Out-File FileList.txt btw a FileName/Name property would be a nice thing, too. Returns, well - the file name without the path ;-) PS > Get-Hash *.ps1,*.cs | Select HashString, Name | Out-File FileList.txt > I guess it depends on whether it is going to be more common for folks to > want to hash files or strings. Files, no question (to me ;-) ). cu Max |
My System Specs![]() |
![]() |
| Thread Tools | |
| Display Modes | |
| |
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| CTP: Script cmdlet parameter attributes error | Shay Levi | PowerShell | 6 | 12-12-2007 01:52 AM |
| cmdlet parameter sets | Darren Mar-Elia | PowerShell | 13 | 11-08-2007 06:41 AM |
| Style of cmdlet parameter names | Roman Kuzmin | PowerShell | 3 | 12-24-2006 01:50 PM |
| Cmdlet Parameter Positon | Keith Hill [MVP] | PowerShell | 2 | 11-23-2006 02:31 PM |
| Alias name in parameter prompt instead of cmdlet name | Jouko Kynsijärvi | PowerShell | 3 | 05-23-2006 06:19 PM |