do we need PscxInputObjectCommandBase?

Topics: Developer Forum
Developer
Mar 16, 2007 at 12:16 AM
I find myself needing PscxInputObjectPathCommandBase without the Path bits -- how best to proceed?
Developer
Mar 16, 2007 at 12:47 AM
I'll do the refactoring we talked about the other day...
Developer
Mar 16, 2007 at 12:59 AM
Ah, I remember now. That looks like a good step forward.

In the long run it would be good to come up with a design that's less filesystem provider centric. It's quite hairy at the moment to derive from our base commands to create cmdlets to work on the registry (or directoryservices, or gac or whatever) paths. The -Path parameter should be provider agnostic, perhaps with some way to configure accepted providers, much like the InputObject is configured by RegisterInputObject<> calls.

thoughts?

Developer
Mar 16, 2007 at 1:19 AM
It's there, your command only needs to provide the parameter property and call ProcessInputObject from ProcessRecord.
Developer
Mar 16, 2007 at 1:47 AM
Edited Mar 16, 2007 at 2:01 AM
I agree, the PscxPathInputObjectBase class should be absolutely provider-agnostic. Could you guys look on my shelveset "Provider-agnostic PscxPathInputObjectCommandBase"?

The PscxCmdlet checks whether the input PSObject has a PSPath property and stores it in the CurrentInputObjectPath instance variable.
The PscxInputObjectPathCommandBase provides a RegisterPathInputType<T>, which registers a ProcessPath(CurrentInputObjectPath) call as the handler of the T objects.

Thoughts?
Developer
Mar 19, 2007 at 3:28 PM
looks ok to me. Will this break much if you check this in?
Coordinator
Mar 19, 2007 at 10:34 PM
Edited Mar 19, 2007 at 10:35 PM
On a somewhat related topic, the one minor drag of these base classes is that the property attributes are fixed unless we provide multiple base classes with slightly differing attributes. For instance, I would like to be able to use Format-Xml like so:

"<a><b></b></a>" | fxml
but that doesn't work because the accept pipeline input attribute for the Path parameters specifies ByPropertyName and ByValue. Since the input is a string it gets routed to the Path parameter. I have to do this instead:

"<a><b></b></a>" | fxml -InputObject {$_}
In the case of this cmdlet (and probably Format-Hex) I would like to specify just ByPropertyName so that the original syntax would be allowed. However this would mean that this won't work:

'foo.xml' | fxml
but I think that is OK. Thoughts?
Developer
Mar 20, 2007 at 8:46 PM
I think I'm with you on this Keith -- {'foo.xml' | fxml} always looked a little weird to me anyway. In my head, that should be {gc foo.xml | fxml} -- so I guess I agree with you in principal. What breaks if we change this? I don't think there's anything wrong with creating a wider range of base classes if we need to fork one of them. We just need to name them well so there's no confusion. I think your first example is a great illustration of why usage patterns should drive our designs; that's the first thing I would try with {fxml} - it should accept a piped in string, no question about it.
Coordinator
Mar 21, 2007 at 6:38 AM
Well it would break if you used 'foo.xml' | fxml which I don't think is a common usage. The other way that I can think of would be if you did 'gci *.xml -name | fxml'. This also doesn't seem very likely. Is there any other thing that outputs filenames as pure strings instead of a FileInfo object that has a Path/PSPath parameter?
Developer
Mar 21, 2007 at 2:43 PM
Not that I can think of - if something is outputting strings as filenames, that's obviously not the "powershell way." The only strings that should ever come out of a cmdlet or provider are data. objects, objects, objects!
Developer
Apr 1, 2007 at 4:00 PM
hmmm - the changes that we did, while good, are not quite enough. The path resolving functionality as it stands is still filesystemprovider centric. The problem stems from the fact that the path that is pushed to ProcessPath is actually a provider-internal path, taken from Get(Un)resolvedProviderPathFromPSPath. You don't really notice this with the filesystem provider because the PSDrive names are the same as the Root, e.g. PSDrive C's root is C:\

Example (assume PscxPathCommandBase):

my-command -path c:\temp\file.ext

This results in "c:\temp\file.ext" being passed to ProcessPath. Yep, that looks fine, except try it again with a new psdrive called mydrive for example, also with a root to c:\

my-command -path mydrive:\temp\file.ext

ProcessPath receives "c:\temp\file.ext", not mydrive:\temp\file.ext. Now you can probably see where the problem is. This is especially obvious when we want to work with other providers on the path. Lets try this with the gac drive:

my-command -path gac:\system.web

ProcessPath receives "system.web" doh. Derived commands get no information about what sort of path that is. So, what's the solution? Pretty straightforward -- we should be passing down System.Management.Automation.PathInfo objects, not strings. We can get them by processing the path/literal path parameter with

Collection<PathInfo> pathInfos = SessionState.Path.GetResolvedPSPathFromPSPath(path);

instead of

Collection<string> rpaths = GetResolvedProviderPathFromPSPath(path, out provider);

PathInfo objects contain the drive, path, providerinfo and providerpath information: Everything we need.

I'm creating a work item for this, and since I've done the research, I'm probably in the best position for this bit, so I'll assign it to me and perform an impact assessment before committing anything.

Developer
Apr 1, 2007 at 4:24 PM
This discussion has been copied to Work Item 9298. You may wish to continue further discussion there.
Developer
Jun 12, 2007 at 8:15 PM

rkeithhill wrote:
"<a><b></b></a>" | fxml
but that doesn't work because the accept pipeline input attribute for the Path parameters specifies ByPropertyName and ByValue.


I know this is ancient and I'm not really contributing to the discussion, but just for the record, this works:

[xml]"<a><b></b></a>" | fxml