Change object properties from get to get ; set

by Daveyboy at 2012-08-16 06:10:03

Hello powershell.org,

How do I change a property of an object from get only to get; set . Below is the sample code, I wish to change “clientcredentials” to be {get ; set } . Never quite picked up on this concept in powershell101.

$proxy |gm


TypeName: ReservationInvoiceServiceClient

Name MemberType Definition
---- ---------- ----------
Abort Method System.Void Abort()
BeginClose Method System.IAsyncResult BeginClose(System.AsyncCallback callback, System.Object state), System.IAsyncResult BeginClose(System.TimeSpan timeout, System.AsyncCa…
BeginOpen Method System.IAsyncResult BeginOpen(System.AsyncCallback callback, System.Object state), System.IAsyncResult BeginOpen(System.TimeSpan timeout, System.AsyncCall…
Close Method System.Void Close(), System.Void Close(System.TimeSpan timeout)
DisplayInitializationUI Method System.Void DisplayInitializationUI()
Dispose Method System.Void Dispose()
EndClose Method System.Void EndClose(System.IAsyncResult result)
EndOpen Method System.Void EndOpen(System.IAsyncResult result)
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetReservation Method Company.Product.IWeb.ReservationResponse, 0ofr1eqk, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null GetReservation(Companys.Product.IWeb.Reservatio…
GetType Method type GetType()
Open Method System.Void Open(), System.Void Open(System.TimeSpan timeout)
ToString Method string ToString()
ChannelFactory Property System.ServiceModel.ChannelFactory`1[[IReservationInvoiceService, 0ofr1eqk, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]] ChannelFactory {get;}
ClientCredentials Property System.ServiceModel.Description.ClientCredentials ClientCredentials {get;}
Endpoint Property System.ServiceModel.Description.ServiceEndpoint Endpoint {get;}
InnerChannel Property System.ServiceModel.IClientChannel InnerChannel {get;}
State Property System.ServiceModel.CommunicationState State {get;}
by JeffH at 2012-08-16 06:43:53
You can’t decide what is writable and what isn’t unless you’re the developer. If a property is read-only (ie get) there’s nothing you can do about it.
by Daveyboy at 2012-08-17 05:32:20
Good information , but for a custom object, how do you change ?
by JeffH at 2012-08-17 06:03:16
Who or what is creating the custom object? This is something that would have to be done with whatever code is creating the object. You can’t do it after the fact.
by RichardSiddaway at 2012-08-17 08:54:14
If you are creating a new PSObject the properties are read/write

if you want read only properties you would need to create a .NET class and compile with Add-type.
by poshoholic at 2012-08-17 09:28:51
Actually that’s not true.

If you are creating a custom object, you can create read-only properties either by using Import-Module -AsCustomObject with some variables defined as read-only, or you can use Add-Member with the ScriptProperty member type to define properties that are read-only. NoteProperties create through Add-Member are always read-write. So are properties assigned through the New-Object -Property parameter, as well as properties defined through simple read-write variable assignments in a call to Import-Module -AsCustomObject. But you can absolutely create read-only properties on custom objects in PowerShell without using Add-Type and C# or some other .NET language, either using the ScriptProperty member type or using NoteProperties defined via Import-Module -AsCustomObject with read-only variables.

For some good examples of this, see the following post:

viewtopic.php?f=5&t=15

Now, regarding the original question about changing properties from read-only to read-write so that you can set them, that’s possible too by overriding the property (using Add-Member to push a new property with the same name on top of the existing property). You have to question though what you are trying to do with this, because if you don’t own the object then this is quite likely the wrong approach. If you can share the bigger picture about what you are trying to do here, then I can probably offer some suggestions.
by Daveyboy at 2012-08-17 10:22:48
Thanks for the reply. I am trying to use powershell to do functional testing against a WCF webservice. I used this script http://poshcode.org/3230 as it appears the New-WebServiceProxy is not compatible with WCF. Right now, I can see the members of the webservice throgh the web proxy, however , I need to authenticate first ( i have been provided with a username and pass) . I know a lot of the answers depend on the web service itself but perhaps I am missing some underlying concepts. In any case, here is the documentation on how to connect, I just need the larger picture explained in powershell terms and I can most likely fill in the blanks myself. Sorry for changing the context of the thread.

"To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:

svcutil.exe https://services2training.somedomain.ca … e.svc?wsdl

This will generate a configuration file and a code file that contains the client class. Add the two files to your client application and use the generated client class to call the Service. For example:

C#

class Test
{
static void Main()
{
ReservationInvoiceServiceClient client = new ReservationInvoiceServiceClient();

// Use the ‘client’ variable to call operations on the service.

// Always close the client.
client.Close();
}
}
"
further

"
You will need to add your web service API credentials to the web service client. For example (.NET):

WebSericeClient.ClientCredentials.UserName.UserName = “username”;
WebSericeClient.ClientCredentials.UserName.Password = “password”;
by poshoholic at 2012-08-17 13:01:10
Ok, I follow what you’re trying to do now. Based on the information you provided here, and on the results of some quick searching around on the web, you’re going to need to modify the Get-WsdlImporter function you got from PoshCode. In its current implementation it does not support using alternate credentials. But the underlying objects that are used (in particular the System.ServiceModel.Description.MetadataExchangeClient object) do support using alternate credentials, so it’s simply a matter of adding support for passing them in.

Here’s a quick untested kick at the can to expose this by adding a -Credential parameter to the Get-WsdlImporter function:

function global:Get-WsdlImporter(
[CmdletBinding()]
[Parameter(Mandatory=$true, ValueFromPipeline=$true)][string]$WsdlUrl,
[Parameter()][ValidateNotNull()][System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
[switch]$HttpGet
) {
if($HttpGet)
{
$local:mode = [System.ServiceModel.Description.MetadataExchangeClientMode]::HttpGet
}
else
{
$local:mode = [System.ServiceModel.Description.MetadataExchangeClientMode]::MetadataExchange
}

$mexClient = New-Object System.ServiceModel.Description.MetadataExchangeClient([Uri]$WsdlUrl, $mode);
$mexClient.MaximumResolvedReferences = [System.Int32]::MaxValue
if ($Credential -ne [System.Management.Automation.PSCredential]::Empty) {
$mexClient.HttpCredentials = $Credential.GetNetworkCredential()
}
$metadataSet = $mexClient.GetMetadata()
$wsdlImporter = New-Object System.ServiceModel.Description.WsdlImporter($metadataSet)

return $wsdlImporter
}


That should either be really close to what you need, or it might just work. I made the following changes to that function:

1. Add a Credential parameter to the function, with the default value being an empty credential. This is the key thing that was missing. This credential is configured so that you can pass in a string (username) and it will prompt you for a password. Or you can use Get-Credential to get the credential and then pass that in. Either will work.
2. Update the function body to assign the credential to the $mexClient object, but only if a non-Empty credential was passed in.

The resulting function should do the job for you. As highlighted, I couldn’t test it directly myself. It isn’t the cleanest script, and I don’t love the style in which it was written, but I didn’t want to stray from what you were already working with so I tried to make my changes in such a way that they followed the style that was already there.

Give that a try and see if that either fixes your problem or sends you on the right path towards getting it fixed.
by Daveyboy at 2012-08-20 08:18:32
The -credentials parameter will allow for the passing of the username/pass , however, It appears I am not authenticated. Am I suppose to create a new object of type ReservationInvoiceServiceClient and change the property of clientcredentials to the username and pass provided (since the api one is read only), if that is the case, I get :

$test = new-object ReservationInvoiceServiceClient
New-Object : Exception calling “.ctor” with “0” argument(s): “Could not find default endpoint element that references contract ‘IReservationInvoiceService’ in the ServiceModel client
configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.”

$proxy.clientcredentials


IssuedToken : System.ServiceModel.Security.IssuedTokenClientCredential
UserName : System.ServiceModel.Security.UserNamePasswordClientCredential
ClientCertificate : System.ServiceModel.Security.X509CertificateInitiatorClientCredential
ServiceCertificate : System.ServiceModel.Security.X509CertificateRecipientClientCredential
Windows : System.ServiceModel.Security.WindowsClientCredential
HttpDigest : System.ServiceModel.Security.HttpDigestClientCredential
Peer : System.ServiceModel.Security.PeerCredential
SupportInteractive : True


$proxy.clientcredentials.UserName

UserName Password
-------- --------

$proxy.state
Created
by poshoholic at 2012-08-20 11:46:55
Wait, just to confirm something, when you call Get-WsdlImporter are you using the -HttpGet switch? Because the credentials change I made was for HttpGet. There are other credentials available on the MetadataExchangeClient class too that I didn’t use.
by Daveyboy at 2012-08-20 11:52:40
Yes, using -http switch.

$wsdlimporter = Get-WsdlImporter ‘https://services2training.somedomain.ca/AmIWebResInvoice/ReservationInvoice.svc?wsdl’ -Credential “vjuser” -HttpGet
$proxyType = Get-WcfProxyType $wsdlImporter
$endpoints = $wsdlImporter.ImportAllEndpoints();
$proxy = New-Object $proxyType($endpoints[0].Binding, $endpoints[0].Address);
by poshoholic at 2012-08-20 12:50:16
Well, without a debugger, without access to the same web services you are using, and without deeper knowledge in this area, I’m not sure what’s missing now. I just reached out to Christian Glessner (@cglessner), the author of the PS2WCF script you’re using, to see if he can lend a hand. I’ll also ping a few developers I know who work with PowerShell since they may have already done this at one point or another. Hopefully more help to come.
by Daveyboy at 2012-09-07 05:33:09
Any word or further ideas on this? Also, is it possible to connect to an API using the webservices client in the .net framework, does the webservices .net client include a “proxy”?
by stevenmurawski at 2012-09-07 09:57:30
Have you tried New-WebServiceProxy? It’s a core cmdlet starting in V2.

I’ve used it successfully to test ASMX and WCF services.
by stevenmurawski at 2012-09-07 10:01:13
Just went back and read the whole thread…

WCF is compatible with New-WebServiceProxy, just make sure you point it at the WSDL.
by Daveyboy at 2012-09-07 10:46:34
I tried New-WebServiceProxy and it will not work when API requires authentication, do you know of a test endpoint that uses WCF and authentication that I could try? . The understanding on the web forums is that there are some limitations with the New-WebServiceProxy cmdlet and WCF?
by poshoholic at 2012-09-07 11:32:52
Hi again,

It turns out I logged a Connect bug about this problem a few years ago: http://connect.microsoft.com/PowerShell … oxy-server. I knew it was ringing a bell. :slight_smile:

That doesn’t help you resolve the issue, but I think this requires .NET and modification of the code you have already or modification of Lee Holmes’ Cookbook script as identified here: http://stackoverflow.com/questions/4083 … oxy-server.

Unfortunately I don’t have time to work out the details for those modifications myself, and I’m not working behind a proxy server to test them out.
by Jaykul at 2012-09-08 15:41:09
It looks like this might have been resolved already, but if not, the answer to your question “does the webservices .net client include a “proxy”?” is that it sort of does, but that’s what the code you’re using from PoshCode creates, and it’s what New-WebServiceProxy creates, and of course, that’s what svcutil creates. The least fragile way of doing what you’re trying to do is to run svcutil as suggested and modify the generated code, and then use Add-Type with that C# code to compile it on-demand in PowerShell.

However, you really should be able to interact with that service using New-WebServiceProxy, as suggested by others, just point it at the same ?wsdl address that’s in your documentation :wink: