Minding Path Inputs in a Cmdlet
When I was a Monad neophyte, I was asked to write a Cmdlet taking a file path as a parameter. A big mistake I made was not keeping in mind that in Monad the FileSystem provider was just one of the many providers. (This makes Monad different from many other shells where you are always in a directory.) For a path-taking Cmdlet, this means two things. The first is that the input path can be specifying a non-FileSystem provider such as the registry provider. The second is that the Cmdlet can be invoked from a non-FileSystem provider. This makes a relative input path not relative to the FileSystem provider. Besides the provider issues, a path in Monad can also be drive-qualified or home-relative. Also, a drive can be mounted at a location that is not the root of the file system.
To deal with all these conditions, the Cmdlet needs to call SessionState.Path.GetResolvedProviderPathFromMshPath and checks the provider returned . If the path does not exist, SessionState.Path.GetUnresolvedProviderPathFromMshPath is used. However, as of Beta 3, this API does not return the provider. We are looking to add a version that does return the provider in V1. As usual, we can't promise this will happen.
In future versions, we hope to provide enough functionalities so that Cmdlets that writes to a path can use InvokeProvider.Content.GetWriter(path). This enables the Cmdlet to write to any provider that implements the IContentCmdletProvider interface. Moreover, the Cmdlet does not need to worry about what provider a path specifies. Again, we can't promise this will happen.
--
Kevin Loo [MSFT]
Microsoft Command Shell Development
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.
Comments
- Anonymous
January 30, 2006
After reading this posting, I found out all of my cmdlets that write to files would fail when invoked from anywhere outside of the file system provider. Now, I need to go back and fix them.
Thanks for bringing this up. - Anonymous
February 01, 2006
I notice you didn't say anything about the MshPath attribute; this seems to me to be the preferable way of doing things...
Also, how should we handle writing binary files? We can't really get a stream to write to, can we? Do we just have to go through the System.IO namespace?
Nick - Anonymous
February 01, 2006
The comment has been removed - Anonymous
February 02, 2006
I can't seem to get set-content to work with binary data, or maybe it's get-content.
For example, if I have a binary file "test.doc" and I want to copy it to test2.doc:
new-item test2.doc -t file; get-content test.doc | set-content test2.doc;
test2.doc is not a valid Word file, even though test.doc is. What should I be doing here?
Thanks for the responsiveness!
Nick - Anonymous
February 02, 2006
Thanks for the advice! I've switched all my cmdlets to take strings and run them through the resolution methods.
As far as binary content, I can't seem to get set-content to work (or maybe it's get-content):
get-content test.doc | set-content test2.doc
Word says that test2.doc is not a valid Word file after doing this, but test.doc is. Am I doing something wrong?
Nick - Anonymous
February 06, 2006
Try using the -encoding parameter for set-content. It can take a value of "byte".
Jeff Jones
Technical Lead
Monad Development
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights. - Anonymous
February 07, 2006
That worked; thanks a lot!
Another question: would it be possible to factor the encoding functionality into something public? It seems that it would apply to more providers than just FS (for example, I use an Encoding parameter on get-uri, a wget analog).
Thanks again,
Nick