Recommended solution for scripting file operations over WebDAV? - powershell

I have a task: files available over WebDAV on a remote server (SSL required) must be checked for whether they may have been updated recently, and if so copied to a local folder. There are a number of other actions that need to be performed after they arrive (copied to other folders, processed, etc.). The operating system I'm working from is Windows 2003 Server. I'd love to be able to use PowerShell for this task.
Naturally, I need to browse the files. I've looked tentatively at several solutions:
Trying to map a drive using "net use" (so far, I get a system 67 error)
Using a product like WebDrive to map a drive (as it happens, WebDrive and another utility on the server seem to conflict with each other for mysterious reasons)
Browse and manipulate the files by issuing http requests using the .NET HTTPWebRequest object hierarchy through PowerShell (works, but seems a bit complicated)
Purchase a commercial .NET assembly that simplifies working with WebDAV (ones that I've seen look pricey)
Have you needed to do something similar? Which approach is best? Any that I have missed? TIA.

It will work from powershell. Note this example:
http://thepowershellguy.com/blogs/posh/archive/2008/05/31/cd-into-sysinternals-tools-from-powershell.aspx
The problem is that the 'web client service' not running on the windows 2003 server (it's disabled by default).
The clue was the "System 67 error"
I confirmed this from a win2k3 server, starting the 'web client service' will get WebDAV working (and probably powershell). It will work out of the box on an XP client (service is running by default).
Let me know if this doesn't resolve it for you.

As an alternative to PowerShell, you could always do this from a WSH script. Example:
<job>
<reference object="ADODB.Connection"/>
<object id="cnIPP" progId="ADODB.Connection"/>
<object id="recDir" progId="ADODB.Record"/>
<script language="VBScript">
Option Explicit
Private waArgs
Private strSubDir
Private rsItems
Private strLine
Set waArgs = WScript.Arguments
If waArgs.Count < 3 Then
WScript.Echo "Parameters: FolderURL User PW [SubDir]"
WScript.Quit
End If
cnIPP.Open "Provider=MSDAIPP.DSO;Prompt=NoPrompt;" _
& "Connect Timeout=10;" _
& "Data Source=" & waArgs(0), _
waArgs(1), waArgs(2), adConnectUnspecified
If waArgs.Count = 4 Then
strSubDir = waArgs(3)
Else
strSubDir = vbNullString
End If
Set waArgs = Nothing
recDir.Open strSubDir, cnIPP, adModeRead, adFailIfNotExists, _
adDelayFetchFields Or adDelayFetchStream
Set rsItems = recDir.GetChildren()
With rsItems
WScript.Echo .Fields("RESOURCE_PARENTNAME").Value
Do Until .EOF
If .Fields("RESOURCE_ISCOLLECTION").Value Then
strLine = " [DIR] " & .Fields("RESOURCE_PARSENAME").Value
Else
strLine = " " _
& " " & .Fields("RESOURCE_PARSENAME").Value _
& " " & CStr(.Fields("RESOURCE_LASTWRITETIME").Value)
End If
WScript.Echo strLine
.MoveNext
Loop
.Close
End With
Set rsItems = Nothing
recDir.Close
cnIPP.Close
</script>
</job>
A sample run:
D:\Scripts>cscript WebDAV.wsf https://my.dav.com/~fred fred fredPW
Microsoft (R) Windows Script Host Version 5.7
Copyright (C) Microsoft Corporation. All rights reserved.
https://my.dav.com/~fred
junk.htm 2/26/2008 4:28:44 AM
test.log 3/30/2009 12:30:45 PM
[DIR] _private
[DIR] stuff
D:\Scripts>
This approach should work with both WebDAV and FrontPage enabled servers without change. The example defaults to protocol auto-negotiation.
To actually retrieve data you'd open an ADODB.Stream on an ADODB.Record opened on the non-directory item.

Related

How to automate VPN connection on Windows 10

I'm going to be traveling for the next month, and I'd like to automate the VPN connection process so that on X event, the script fires and automatically connects me. I've already configured the [L2TP/IPSec] VPN connection in ms-settings:network-vpn & verified it works, but it's automation step that's proving problematic.
Windows GUI: The credentials have been saved.
PowerShell: The RememberCredential property is set to True
VBScript: Curiously, the VPN connection is hidden:
Dim oShell : Set oShell = CreateObject("Shell.Application")
Dim NetConn : Set NetConn = oShell.Namespace(49)
Dim Connections : Set Connections = NetConn.Items
wscript.echo "Connection Count [" & Connections.Count & "]"
For i = 0 to Connections.Count - 1
wscript.echo "Connections.Item(" & i & ").Name: [" & Connections.Item(i).Name & "]"
next
rasdial <entry>: Expectedly returns error 691.
rasphone -d <entry>: Displays the Connection dialog whereas I'd prefer it to just connect automatically and hidden.
Is this even possible in Windows 10? Or am I just overlooking some small yet key detail?
I ended up leveraging Add-VpnConnectionTriggerApplication to trigger an automatic connection of the VPN on the launch of specific executables/UWP applications. The downside is that when doing this, PoSh warns that SplitTunneling must be enabled which is less than ideal.
However after playing around with it for a while (just 2 or so hours now) to ensure the VPN keys off specific executables/UWP's, I ended up disabling SplitTunneling and, paradoxically, it appears to continue working as I would hope/expect. I rebooted a few times, logged on and sure enough by the time the desktop loaded the VPN had been established.
I need to do more testing to confirm, but this is sufficient to help save me from myself.
I do this by checking the Remember my sign-in info checkbox when I created the VPN connection.
You can check this in your PowerShell script by ensuring that Get-VpnConnection returns RememberCredential : True.
If this is the case, then rasdial should automatically connect it.
I do it with this:
<#
.SYNOPSIS
Ensures vpn connection (assumed to have saved credentials) is connected.
#>
function Connect-Vpn
{
[CmdletBinding()]
param (
[object]
$Settings
)
$rr1 = Get-VpnConnection -Verbose:$false | where {$_.ServerAddress -imatch $Settings.VpnConnectionPattern -and $_.RememberCredential} | Select -First 1
if ($rr1.ConnectionStatus -ne 'Connected')
{
rasdial.exe $rr1.Name
If (-not $LASTEXITCODE)
{
throw "Cannot connect to '$($rr1.Name)'."
}
}
else
{
Write-Verbose "Already connected to '$($rr1.Name)'."
}
}
You will have to massage this code to your needs as this uses some fields from my settings file...

Modify datasource IP addresses in WebSphere Application Server

I have nearly a hundred data sources in a WebSphere Application Server (WAS) and due to office relocation, the IP of the database servers have changed and I need to update the datasource IP addresses in my WAS too.
Considering it error-prone to update hundred IPs through admin console.
Is there any way that I can make the change by updating config files or running a script? My version of WAS is 7.0.
You should be able to use the WAS Admin Console's built-in "command assistance" to capture simple code snippets for listing datasources and changing them by just completing those operations in the UI once.
Take those snippets and create a new jython script to list and update all of them.
More info on command assistance:
http://www.ibm.com/developerworks/websphere/library/techarticles/0812_rhodes/0812_rhodes.html
wsadmin scripting library:
https://github.com/wsadminlib/wsadminlib
You can achieve this using wsadmin scripting. Covener has the right idea with using the admin console's command assistance to do the update once manually (to get the code) and then dump that into a script that you can automate.
The basic idea is that a datasource has a set of properties nested under it, one of which is the ip address. So you want to write a script that will query for the datasource, find its nested property set, and iterate over the property set looking for the 'ipAddress' property to update.
Here is a function that will update the value of the "ipAddress" property.
import sys
def updateDataSourceIP(dsName, newIP):
ds = AdminConfig.getid('/Server:myServer/JDBCProvider:myProvider/DataSource:' + dsName + '/')
propertySet = AdminConfig.showAttribute(ds, 'propertySet')
propertyList = AdminConfig.list('J2EEResourceProperty', propertySet).splitlines()
for prop in propertyList:
print AdminConfig.showAttribute(prop, 'name')
if (AdminConfig.showAttribute(prop, 'name') == 'ipAddress'):
AdminConfig.modify(prop, '[[value '" + newIP + "']]')
AdminConfig.save();
# Call the function using command line args
updateDataSourceIP(sys.argv[0], sys.argv[1])
To run this script you would invoke the following from the command line:
$WAS_HOME/bin/wsadmin.sh -lang jython -f /path/to/script.py myDataSource 127.0.0.1
**Disclaimer: untested script. I don't know the name of the "ipAddress" property off the top of my head, but if you run this once it will print out all the properties on your ds, so you can get it there
Some useful links:
Basics about jython scripting
Modifying config objects using wsadmin
As an improvement to aguibert's script, to avoid having to provide all 100 datasource names and to update it to correct the containment path of the configuration id, consider this script which will update all datasources, regardless of the scope at which they're defined. As always, backup your configuration before beginning and once you're satisified the script is working as expected, replace the AdminConfig.reset() with save(). Note, these scripts will likely not work properly if you're using connection URLs in your configuration.
import sys
def updateDataSourceIP(newIP):
datasources = AdminConfig.getid('/DataSource:/').splitlines()
for datasource in datasources:
propertySet = AdminConfig.showAttribute(datasource, 'propertySet')
propertyList = AdminConfig.list('J2EEResourceProperty', propertySet).splitlines()
for prop in propertyList:
if (AdminConfig.showAttribute(prop, 'name') == 'serverName'):
oldip = AdminConfig.showAttribute(prop, 'value')
print "Updating serverName attribute of datasource '" + datasource + "' from " + oldip + " to " + sys.argv[0]
AdminConfig.modify(prop, '[[value ' + newIP + ']]')
AdminConfig.reset();
# Call the function using command line arg
updateDataSourceIP(sys.argv[0])
The script should be invoked similarly to the above, but without the datasource parameter, the only parameter is the new hostname or ip address:
$WAS_HOME/bin/wsadmin.sh -lang jython -f /path/to/script.py 127.0.0.1

CQ5 is not getting installed as publisher in windows service

I am trying to install the AEM CQ as windows service in publish mode. But it is getting installed as an author.
I have changed the variable to publish in instsrv.bat
D:\AdobeAEM\crx-quickstart\opt\helpers\instsrv.bat
:: runmode(s)
set cq_runmode="publish"
:: HTTP port
set cq_port=4503
Still, it is opening in author mode.
I have not configured author in this server
Am I missing something?
if you are working con CQ5.5 It's ok, but in AEM(5.6) It's impossible to install it as publish mode if you installed it as author before.
Based on what you described it sounds like you added JVM parameters to the jvm_options variable without separating the values with the # character. If you don't separate them with '#' or ';' then the runmode will not get included in the --JvmOptions= parameter passed to prunsrv. See the section code below from instsrv.bat which shows this.
:: default JVM options
:: separate multiple entries by ";" or "#"
:: if you need these chars put them inside single quotes
set jvm_options=-XX:MaxPermSize=256M
::* ------------------------------------------------------------------------------
::* do not configure below this point
::* ------------------------------------------------------------------------------
set main_class=org.apache.sling.launchpad.app.Main
set start_param=start#-c#.#-i#launchpad
if defined cq_runmode (set jvm_options=%jvm_options%#-Dsling.run.modes=%cq_runmode%)
Part of script that calls prunsrv:
:run_install
chdir /D %~dp0
prunsrv //IS//%service_name% --Description="%service_description%" --DisplayName="%service_name%" --Startup="%service_startmode%" --StartPath=%context% --Classpath=%CQ_JARFILE% --JvmMx=%jvm_mx% --JvmOptions=%jvm_options% --StdOutput=%context%\logs\startup.log --StdError=%context%\logs\startup.log --LogPath=%context%\logs --PidFile=..\conf\cq.pid --StartMode jvm --StartClass=%main_class% --StartParams=%start_param% --StopMode=jvm --StopClass=%main_class% --StopParams=%stop_param% --Jvm=%jvm_path%
if defined start (net start %service_name%)
goto exit

Status for connector session is: 1544 Message: Code # 0 Connector Message: Error: Cannot find Connector 'DB2'

I have a database with two agents, well there are really more than two, but two that matter right now. One works, the other does not. Both have Uselsx '*lsxlc' defined in (Options).
I have commented out everything in the failing agent except
Dim s As New NotesSession
Dim db As NotesDatabase
Dim agentLog As NotesLog
Set db = s.CurrentDatabase
'agent log
Set agentLog = New NotesLog("Customers from Aging Report - AKM")
Call agentLog.OpenNotesLog( db.server, "agentinfo.nsf" )
agentLog.LogActions = True 'Set to True/False to turn on/off action logging
agentLog.LogErrors = True 'Set to True/False to turn on/off error logging
Call agentLog.LogAction("Start Agent: GetCustomerDataBasedOnAging")
On Error Goto throwError
Dim lcses As New LCSession
Dim src As New LCConnection(COutConn)
%REM
....
%END REM
Exit Sub
throwError:
'Error code
Dim epos As String
Dim emsg As String
Dim msg As String
Dim result As String
Dim status As Integer
Dim msgcode As Long
If lcses.status <> LCSUCCESS Then
status = lcses.GetStatus (result, msgcode, msg)
Call agentLog.LogError( msgcode,"Status for connector session is: " & Cstr(status) & Chr(10) & "Message: " & msg & " Code # " & Cstr(msgcode) & Chr(10) & "Connector Message: " & result )
emsg = "Customers from Aging Report' Agent: ("+Cstr(Erl)+") "& "[" &Cstr(Err) & "] [" & Error$ & "]"
Call agentLog.LogError( Err, emsg)
Else
emsg = "Customers from Aging Report' Agent: ("+Cstr(Erl)+") "& "[" &Cstr(Err) & "] [" & Error$ & "]"
Call agentLog.LogError( Err, emsg)
End If
Resume Next
COutConn is defined as a constant with value 'DB2'
I get the following error in the agent log:
Status for connector session is: 1544
Message: Code # 0
Connector Message: Error: Cannot find Connector 'DB2'
This happens whether I use the constant COutConn, or "DB2".
The strange thing is that the other agent with the same definitions works properly. I know DB2 exists on the machine, it is i5/OS v5r4. DB2 is built in on this operating system.
What else do I need to look for?
The answer is, be sure you know which machine the agent is running on. When you right click the agent in Domino Designer, and select Run, as I did, the agent is not running on the server that the database resides on, but rather inside the Domino Designer client. that is going to be Windows or Linux depending on your workstation.
So why did the one agent work while the other did not? Well the one that worked was activated from a button in the Notes Client, and the function attached to the button used Run on Server. The server was indeed IBM i. However, in the case of the failing agent, I executed that one from within Domino Designer as mentioned above, thus no DB2 connector.
Here's to hoping someone can learn from my pain!

Windows Search equivalent to Indexing Services "vpath" and "characterication"

I'm trying to move a website that was on:
Windows 2003,
IIS 6, and
Indexing Services
to:
Windows 2008,
IIS 7, and
Windows Search
It's Windows Search that's giving me a problem. I've set up a Windows Search to index the physical folder that contains the site, and I can query for file names, but what is the new equivalent of vpath and characterization?
None of these seem to be the answer.
characterization = System.Search.AutoSummary
Reference
Query the "directory","filename" properties from the Indexing Service. Then, using ASP Classic / VbScript, with RS representing a recordset:
Function MapURL( Path )
' opposite of server.mappath - takes a filesystem path and turns it into a url
Dim AppPath
AppPath = Server.MapPath("/")
path = Replace(path,apppath,"",1,-1,1)
path = Replace(path,"\","/",1,-1,1)
MapURL = path
End Function
Dim vpath
do while not rs.EOF
vpath = rs("directory") & "/" & rs("filename")
response.write MapURL(vpath)
rs.movenext
loop
Based on ASP.NET code from http://geekswithblogs.net/AlsLog/archive/2006/08/03/87032.aspx