How can I configure CDOSYS in IIS 7.5 on Windows 2008? - windows

Like so many of you at the moment I am moving a legacy classic ASP application from a Windows 2003 server to Windows 2008. I have this mostly working but I am unable to send e-mail through it. This is because CDOSYS is not configured correctly. Despite about 4-5 hours' googling and running through API documentation and even searching through all files on the filesystem and the system registry I was unable to figure out where this is set.
The ASP.NET portion of the legacy application works fine. It is able to send e-mails to localhost without authentication which are then passed through to the mail server with authentication for sending to their destination.
I translated the VB6 calls from the source code into a Powershell script for convenience:
$config = new-object -com "CDO.Configuration";
$config.Load(1);
$smtp = new-object -com "CDO.Message";
$smtp.Configuration = $config;
$smtp.From = "me#example.com"
$smtp.To = "me#example.com"
$smtp.Subject = "test"
$smtp.TextBody = "Message";
$smtp.Send();
This script sends an e-mail correctly on my original server. On the new server it returns this error when calling $smtp.Send():
Exception calling "Send" with "0" argument(s): "The "SendUsing" configuration value is invalid.
The configuration between the two servers is quite different. Using the $config reference from above, I executed $config.Fields | Format-List -Property Name,Value on both servers.
Old server (where it works):
Name : http://schemas.microsoft.com/cdo/configuration/languagecode
Value : en-us
Name : http://schemas.microsoft.com/cdo/configuration/postusing
Value : 0
Name : http://schemas.microsoft.com/cdo/configuration/sendusing
Value : 1
Name : http://schemas.microsoft.com/cdo/configuration/smtpserverpickupdirectory
Value : D:\Inetpub\mailroot\Pickup
Name : http://schemas.microsoft.com/cdo/configuration/usemessageresponsetext
Value : True
Name : urn:schemas:calendar:timezoneid
Value : 1
New server:
Name : http://schemas.microsoft.com/cdo/configuration/languagecode
Value : en-gb
Name : http://schemas.microsoft.com/cdo/configuration/postusing
Value : 0
Name : http://schemas.microsoft.com/cdo/configuration/sendusing
Value : 0
Name : http://schemas.microsoft.com/cdo/configuration/usemessageresponsetext
Value : True
Name : urn:schemas:calendar:timezoneid
Value : 0
It seems that all I need to do to make this work is either configure it to by default send mail to localhost, or to drop the mail in the pickup directory. The IIS SMTP server is already configured to look at this directory.
However, I am unable to figure out where these values are set. They must be set in a file or the registry somewhere but even searching through the C drive looking for phrases like "\Pickup" and "usemessageresponsetext" and so on have not revealed anything. If they are somewhere I guess they're in a binary datastore somewhere.
All samples for CDOSYS involve configuring the CDO.Configuration or CDO.Message instance directly but all throughout the code our application loads the configuration from IIS, so somehow this was set at one point by someone.
I missed out on the classic ASP era so I am in very unfamiliar territory. That said, my coworkers who were active classic ASP developers do not know how to configure this, and the original person who set this up has since moved on. It's entirely possible that I'm missing a very simple basic concept here.

I discovered that I was able to use my sample Powershell script when I was logged in as an administrator. Research from that lead me to a post on the IIS forums which has a solution for the issue. Unfortunately it now leads to some dead links which mean it doesn't work. It had enough hints however to put together a solution:
Download and install the IIS Resource Kit Tools.
Execute C:\Program Files (x86)\IIS Resources\Metabase Explorer\MBExplorer.exe as an administrator.
Navigate to /LM/SmtpSvc, right-click on it and select Properties.
Enter the groups you want to give access to. In my case it was both Users and IIS_IUSRS with read access only.
Navigate to /LM/SmtpSvc/1, and set the same permissions on this node also.
Grant read/write access to IIS_IUSRS and Users to c:\inetpub\mailroot
So, the root cause was that the user I was trying to execute this under did not have the correct permissions.
Regrettably I couldn't figure out how to script these steps. The post makes reference to a "metaacl.vbs" script that I couldn't find anywhere; all links that claim to have it are dead. It's also meant to be installed by the IIS Resource Kit tools linked above but I couldn't find it anywhere on my server.
If you could find that somewhere you'd be able to perform the above steps like so:
cscript metaacl.vbs IIS://LOCALHOST/SMTPSVC %computername%\IIS_IUSRS R
cscript metaacl.vbs IIS://LOCALHOST/SMTPSVC/1 %computername%\IIS_IUSRS R

Related

Start Domino service and word

I want to modify a word document from an agent in Lotus Script. Domino server starts as a service with an Administrator user count. The word document is attached in a Lotus Notes document. I extract the document in a folder that Domino has access.
When the Domino server (as service) runs the process, the Domino displays an error. But when I start the Domino server as application, the process runs well and it doesn't get any error.
The script code is the next:
Set rtItem = doc_perfil.GetFirstItem(campo)
Set obj = rtitem.EmbeddedObjects(0)
sFile = RUTA + "\" + ReplaceSubstring(nameNewFile, "/", "-") + ".docx"
Call obj.ExtractFile(sFile)
OLE_OBJECT = "word.application"
Set Word = CreateObject (OLE_OBJECT)
Set templt = Word.Documents.Add (sFile)
The line that produces the error is "Set templt = Word.Documents.Add (sFile)"
As a first point, running Word on a server is totally unsupported by Microsoft.
The quick and dirty way round this is to not run Domino as a service. A service can't interact with the UI which it needs to for OLE.
The downside to this is that the Domino Server will need to be manually restarted if the Windows server ever reboots.
The proper way to do this is to do what you need in java using a library like docx4j or Apache POI. As you don't include any code beyond opening the word doc, I can't comment further on what would be a suitable library.
In the line of code,
Set templt = Word.Documents.Add (sFile)
Add, does not take parameters, please try word.documents.open
If the Domino is not run as a service and still the error occurs, change the security level of the agent to 3 (run will full admin rights)

classic asp create text file on webserver: error 800a0034 Bad_file_name_or_number

I have a classic asp page in VBS and I am trying to create a file on the web server with the following code.
Set fso = CreateObject("Scripting.FileSystemObject")
Set file1 = fso.CreateTextFile("\\localhost\inetpub\wwwroot\cs\batch\123456dirs.bat", true)
This returns the following error:
|666|800a0034|Bad_file_name_or_number
Line 666 is the CreateTextFile line.
According to the Microsoft docs, this means that I'm trying to create a file with an invalid filename. Then it explains the rules for filenames and mine appears to be perfectly valid.
Any suggestions or ideas on how I can further troubleshoot this?
first thing to check to make sure your users have access to the folder. Assuming you're not using windows authentication, make sure IUSR account has write access to the folder.
second, unless inetpub is set up as a share to folder, you're syntax won't work. if the root of your website is located in the CS folder, you can do something like:
Set file1 = fso.CreateTextFile(Server.MapPath( "/cs/batch/123456dirs.bat" ), true)
The createtextfile() function runs on the web server but in the context of the local server itself. Simply put, any path you give it must resolve as if you were logged on to a windows desktop on the server and tried to CD to that path.
The format \localhost... is a UNC path. See this question for a discussion about UNC paths and windows. Unless you know for sure that there is a UNC path mapped for \localhost then that is probably your issue. You may be making the assumption the \localhost will be a reasonable path to use, but as I said unless you know for sure it is available then this is an invalid choice.
Lastly, if you decide to set up a share for \localhost, you will be getting in to some interesting territory around the user context that the web server operates in. You see you will have to set up the share for the IIS user that is configured as the run-as identity for IIS, so you will need to know that and create the required config to give that user the share.
If it were me, I would switch to using a standard windows path, although even then you need to appreciate the run-as user context and security config, etc.

Can I use VS2010 TFS Power Tools PowerShell cmdlets to directly get the contents of a Source Control file into a variable?

I want to use the latest contents of a XAML file stored in TFS Source Control and embed it in a string variable, which is to be submitted as a query to MS SQL Server.
I have been using TFS Power Tools cmdlets in PowerShell (such as Get-TfsChildItem and Select-TfsItem) to successfully get handles on TFS files, changesets and shelvesets. But I cannot identify any methods or properties on these objects that would allow me to directly get the contents of a file into a variable.
I want to do something like this:
$tfsFileName = "$/MyBranch/MyFile.xaml"
$tfsServerName = "http://myTFSServer:8080/tfs"
$tfsServer = Get-TfsServer $tfsServerName
$xamlFile = Get-TfsChildItem -Item $tfsFileName -Server $tfsServer
$xamlContent = (Get-Content $xamlFile)
Is this possible, or do I always have to perform a Get Latest using tf.exe, and then get the contents of the local file?
I think you want the DownloadFile method on an Item. Eg:
$xamlFile = Get-TfsChildItem -Item $tfsFileName -Server $tfsServer
$xamlFile.DownloadFile("C:\Temp\file.xaml")
When I got the message about Team Foundation Services not being available on my server it turns out I had the wrong URI. I originally had http://tfs.mycompanyweb.mycompany.com:8080/tfs/ist/ISTDatabaseTools but changed it to http://tfs.mycompanyweb.mycompany.com:8080/tfs/ist and that error cleared up.
I still fail to get DownloadFile to work properly though. I'm trying to do something similar myself.
Joe

Opening URLs with custom protocol - syntax error?

I'm having some real issues in getting local files to open up via a browser using a custom protocol. Now before you shoot me for the custom protocol, this web app will be working in a closed intranet environment, so I have full control to add these protocols for all users. The app works fine at the moment, but I've been requested to bypass the Open / Save dialog for files as it's 'annoying' and 'time consuming' (yeah, I know...I tried to tell them), so here I am in uncharted territory!
Here's an example then of what's not working (I'm using Notepad in this example to test it in Server 2008 R2 with IIS7):
Using the info on Registering an Application to a URL Protocol I've added the following to the registry:
HKEY_CLASSES_ROOT
opentxt
(Default) = "URL:opentxt Protocol"
URL Protocol = ""
DefaultIcon
(Default) = "C:\Windows\System32\notepad.exe,1"
shell
open
command
(Default) = "C:\Windows\System32\notepad.exe" "%1"
So now, in theory, it should be as easy as having the following link in my html
Open File
And it does almost work - click on the link and it opens up Notepad instantly, however I'm presented with this error in notepad.
The filename, directory name, or volume label syntax is incorrect
The file definitely exists in that location (I can read it using http: //localhost/openme.txt), and I've tried to represent the link in as many different formats, such as described here but just can't get it to work.
Any ideas where I'm going wrong?
Quite simply, you're confusing your two different protocols.
Your protocol - and the Url that you pass to notepad - is opentxt://localhost/openme.txt. The working location of the file is http: //localhost/openme.txt. These two are not the same!
HTTP is a protocol that is natively understood by the operating system and, as such, Notepad can pass the HTTP Url to the operating system, which will in turn connect to localhost using port 80 and send a request for that resource. The file is returned, and Notepad has its data. This is all handled within operating system libraries that define the behaviour of HTTP.
Your opentxt protocol doesn't have this support unless you code it. Notepad doesn't know what to do with it - so you see your error message.
A way to handle this easily is to create your own application that handles the protocol. If you had an opentxtHandler.exe wired up through the registry, it would be passed the opentxt:// url, and can then process it appropriately. This might simply mean changing the protocol from opentxt to http and then passing it to Notepad - or it could be something more complex.

Launching a registered mime helper application

I used to be able to launch a locally installed helper application by registering a given mime-type in the Windows registry. This enabled me to allow users to be able to click once on a link to the current install of our internal browser application. This worked fine in Internet Explorer 5 (most of the time) and Firefox but now does not work in Internet Explorer 7.
The filename passed to my shell/open/command is not the full physical path to the downloaded install package. The path parameter I am handed by IE is
"C:\Document and Settings\chq-tomc\Local Settings\Temporary Internet Files\
EIPortal_DEV_2_0_5_4[1].expd"
This unfortunately does not resolve to the physical file when calling FileExists() or when attempting to create a TFileStream object.
The physical path is missing the Internet Explorer hidden caching sub-directory for Temporary Internet Files of "Content.IE5\ALBKHO3Q" whose absolute path would be expressed as
"C:\Document and Settings\chq-tomc\Local Settings\Temporary Internet Files\
Content.IE5\ALBKHO3Q\EIPortal_DEV_2_0_5_4[1].expd"
Yes, the sub-directories are randomly generated by IE and that should not be a concern so long as IE passes the full path to my helper application, which it unfortunately is not doing.
Installation of the mime helper application is not a concern. It is installed/updated by a global login script for all 10,000+ users worldwide. The mime helper is only invoked when the user clicks on an internal web page with a link to an installation of our Desktop browser application. That install is served back with a mime-type of "application/x-expeditors". The registration of the ".expd" / "application/x-expeditors" mime-type looks like this.
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.expd]
#="ExpeditorsInstaller"
"Content Type"="application/x-expeditors"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ExpeditorsInstaller]
"EditFlags"=hex:00,00,01,00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ExpeditorsInstaller\shell]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ExpeditorsInstaller\shell\open]
#=""
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ExpeditorsInstaller\shell\open\command]
#="\"C:\\projects\\desktop2\\WebInstaller\\WebInstaller.exe\" \"%1\""
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MIME\Database\Content Type\application/x-expeditors]
"Extension"=".expd"
I had considered enumerating all of a user's IE cache entries but I would be concerned with how long it may take to examine them all or that I may end up finding an older cache entry before the current entry I am looking for. However, the bracketed filename suffix "[n]" may be the unique key.
I have tried wininet method GetUrlCacheEntryInfo but that requires the URL, not the virtual path handed over by IE.
My hope is that there is a Shell function that given a virtual path will hand back the physical path.
I believe the sub-directories created by IE are randomly generated, so you won't be able guarantee that it will be named the same every time, and the problem I see with the registry method is that it only works when the file is still in the cache...emptying the cache would purge the file requiring yet another installation.
Would it not be better to install this helper into application data?
I'm not sure about this but perhaps this may lead you in the right direction: try using URL cache functions from the wininet DLL: FindFirstUrlCacheEntry, FindNextUrlCacheEntry, FindCloseUrlCache for enumeration and when you locate an entry whose local file name matches the given path maybe you can use RetrieveUrlCacheEntryFile to retrieve the file.
I am using a similar system with the X-Appl browser to display WAML web applications and it works perfectly. Maybe you should have a look at how they managed to do it.
It looks like iexplore is passing the shell namespace "name" of the file rather than the filesystem name.
I dont think there is a documented way to be passed a shell item id on the command line - explorer does it to itself, but there are marshaling considerations as shell item ids are (pointers to) binary data structures that are only valid in a single process.
What I might try doing is:
1. Call SHGetDesktopFolder which will return the root IShellFolder object of the shell namespace.
2. Call the IShellFolder::ParseDisplayName to turn the name you are given back into a shell item id list.
3. Try the IShellFolder::GetDisplayNameOF with the SHGDN_FORPARSING flag - which, frankly, feels like w'eve just gone in a complete circle and are back where we started. Because I think its this API thats ultimately responsible for returning the "wrong" filesystem relative path.
Some follow-up to close out this question.
Turned out the real issue was how I was creating the file handle using TFileStream. I changed to open with fmOpenRead or fmShareDenyWrite which solved what turned out to be a file locking issue.
srcFile := TFileStream.Create(physicalFilename, fmOpenRead or fmShareDenyWrite);

Resources