Can't find XML in httprequest - c#

I have an existing asp page which largely can't/won't change which calls a service, sending an XML document.
Private Function QueryXYZ(ByVal strStreet1 As String, _
ByVal strStreet2 As String, _
ByVal strCity As String, _
ByVal strState As String, _
ByVal strZipMain As String, _
ByRef objDomDoc As DOMDocument, _
ByRef blnStreetMatch) As Boolean
On Error GoTo errorHandler
Dim intCount As Integer
Dim lngErrNum As Long
Dim objResult As IXMLDOMNode
Dim objResultSet As IXMLDOMNodeList
Dim objXMLHTTP As New ServerXMLHTTP
Dim strErrDesc As String
Dim strFault As String
Dim strMessage As String
Dim strResults As String
Dim strSoap As String
'CO 11784 - start
'Build Soap XML request
strSoap = _
"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance/' xmlns:xsd='http://www.w3.org/2001/XMLSchema/'>" & _
"<soap:Body>" & _
"<MatchAddress xmlns='http://(address/'>" & _
"<MatchParms>" & _
"<Firm />" & _
"<Street1>" & strStreet1 & "</Street1>" & _
"</MatchParms>" & _
"</MatchAddress>" & _
"</soap:Body>" & _
"</soap:Envelope>"
'CO 11784 - end
'Load Request into XML document
objDomDoc.async = False
objDomDoc.loadXML (strSoap)
'Check for syntax errors in Request
If objDomDoc.parseError.errorCode <> 0 Then
Err.Raise 10620, "Query", "Error parsing generated xml query: [" & objDomDoc.parseError.reason & _
"]" & "[" & objDomDoc.parseError.srcText & "]"
End If
'Send the Request
objXMLHTTP.Open "POST", mstrGISURL, False
objXMLHTTP.setRequestHeader "soapaction", "http://sampleaddress.com/MatchAddress"
objXMLHTTP.send objDomDoc
'Load Response
strResults = Replace(objXMLHTTP.responseText, """, """")
strResults = Replace(strResults, ">", ">")
strResults = Replace(strResults, "<", "<")
strResults = Replace(strResults, "&apos;", "'")
objDomDoc.loadXML (strResults)
I want to set it to talk to a new (non-WCF) service I'm writing.
public XmlDocument Matchaddress(string AddressInXML)
(I know that parameter call is almost certainly wrong, it's set that way just to test it using the service.asmx form)
The problem is, I can't find where the XML is located in the request. I've checked the and the input stream with a test function:
System.IO.StreamReader sr = new System.IO.StreamReader(HttpContext.Current.Request.InputStream);
string requestContents = sr.ReadToEnd();
sr.Close();
StreamWriter Sw = System.IO.File.CreateText( #"C:\Temp\testfile.txt");
for (int i = 0; i < HttpContext.Current.Request.Headers.AllKeys.Length; i++)
{
Sw.WriteLine (HttpContext.Current.Request.Headers.AllKeys[i] + Environment.NewLine);
//if (HttpContext.Current.Request.Headers.AllKeys[i] == "SOAPAction")
//{
string soaphd = HttpContext.Current.Request.Headers.AllKeys[i];
string soapTXT = System.Web.HttpContext.Current.Request.Headers[soaphd];
Sw.WriteLine(soapTXT + Environment.NewLine);
//}
}
Sw.Close();
And can't find it.
I am clearly doing something wrong. I'm not sure if there's a change that needs making to that classic ASP code, no matter how hard it will be to do. I can't tell if I need to find the location and then change the input parameter (or remove it entirely) or if I need to know what the right parameter is first, and then the data will magically appear.
I don't know that much about that "soapaction" header - does it need to match the address of the new service, or can it be some generic (or just plain incorrect) other address? Same question for the
<MatchAddress xmlns='http://(address/'>"
line in the XML - could that be bollixing it up by not being a matching address?
I don't even see the XML when I try to run it in SOAPUI, so whether that means anything or not I dunno.
More details can be provided as requested.

Turns out I was close using the stream reader, I was just reading it into the wrong kind of object. This gives me access to the entire XML :
XmlDocument xdoc = new XmlDocument();
using (Stream receiveStream = HttpContext.Current.Request.InputStream)
{
// Move to begining of input stream and read
receiveStream.Position = 0;
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
// Load into XML document
xdoc.Load(readStream);
}
}
Dumping the resulting XML into a string allowed me to get at anything I wanted, any way I care to. No need to worry about the parameters in the function definition at all.

Related

Translating "Bodies to Parts" Macro in CATIA V5 from VBA to C#

I'm trying to convert the Bodies from Parts to Parts in a Product in CATIA. I found a VBA script that works fine, but I have to translate it to C#.
The VBA script is the following:
Sub GreateProductsFromBodies_SelectAllBodies()
On Error Resume Next
Set CATIA = GetObject(, "CATIA.Application")
'Declare variables
Dim oPartDoc As PartDocument
Dim oPart As Part
Dim oProductDoc As ProductDocument
Dim oProduct As Product
'Create a new ProductDoc and rename it's PartNumber equals to Partdoc's PartNumber
Set oPartDoc = CATIA.ActiveDocument
Set oProductDoc = CATIA.Documents.Add("Product")
oProductDoc.Product.PartNumber = oPartDoc.Product.PartNumber
'Arrange windows use "Title Vertically" ,then active window contain Partdoc
CATIA.Windows.Arrange catArrangeTiledVertical
CATIA.Windows.Item(1).Activate
'Check the Body's name use "For ... Next"loop . If Body's name duplicate,then rename.
Dim j As Integer, k As Integer
For j = 1 To oPartDoc.Part.Bodies.Count
For k = 1 To oPartDoc.Part.Bodies.Count
If oPartDoc.Part.Bodies.Item(j).name = oPartDoc.Part.Bodies.Item(k).name And j <> k Then
oPartDoc.Part.Bodies.Item(j).name = oPartDoc.Part.Bodies.Item(k).name & "_Rename_" & j
End If
Next
Next
'Copy Bodies from PartDocument
Dim i As Integer, ProductPN As String, FinalProductPN As String
For i = 1 To oPartDoc.Part.Bodies.Count
With oPartDoc.Selection
.Clear
.Add oPartDoc.Part.Bodies.Item(i)
.Copy
.Clear
End With
'Modify the Product's PartNumber,replace "\" and "."to "_" ,then delete Space
ProductPN = oPartDoc.Part.Bodies.Item(i).name
If Right(ProductPN, 1) = "\" Then
ProductPN = Left(ProductPN, Len(ProductPN) - 1)
End If
FinalProductPN = Replace(Replace(Replace(ProductPN, "\", "_"), ".", "_"), " ", "") 'Replace "\" and "."to "_",Delete Space
'Paste Body in Product's Part as Result
Set oProduct = oProductDoc.Product.Products.AddNewComponent("Part", FinalProductPN) 'Add Part
With oProductDoc.Selection
.Clear
.Add oProductDoc.Product.Products.Item(i).ReferenceProduct.Parent.Part
.PasteSpecial "CATPrtResultWithOutLink"
.Clear
End With
oProductDoc.Product.Products.Item(i).ReferenceProduct.Parent.Part.Update
Next
'Use Msgbox to echo the complete flag
MsgBox "All the select Bodies had been created as a PartDocument successfully !" & Chr(13) & _
">>> The Partdocument's Bodies's count : " & oPartDoc.Part.Bodies.Count & Chr(13) & _
">>> The ProductDocument's PartDocument's count : " & oProductDoc.Product.Products.Count, _
vbOKOnly + vbInformation, "#LSY >>> CATIAVBAMacro of Part to Product >>> Run Result"
End Sub
I translated every line, except the line:
oProductDoc.Selection.Add oProductDoc.Product.Products.Item(i).ReferenceProduct.Parent.Part
I found no corresponding property in C#, cause the last property Part is missing in C#.
I wrote:
oProductDoc.Selection.Add(oProductDoc.Product.Products.Item(i).ReferenceProduct.Parent.??????);
I'm very thankfull for every help!
I solved it, if someone else is in this situation:
I had to cast the line as PartDocument, whish gives me the needed .Part Property!
Before the selection:
PartDocument partDoc = oProductDoc.Product.Products.Item(i).ReferenceProduct.Parent as PartDocument;
And in the required line:
oProductDoc.Selection.Add(partDoc.Part);

Copy document content (including formatting and page format) to another using Word Interop in c# with 100% fidelity

I want to copy the content of a document created by the user to an existing document. The existing document content must be an exact mirror to the document created by the user.
I cannot simply copy the file using System.IO or saving a copy of the document created by the user using SaveAs methods in Word Interop. This is because the existing document is a document that is generated from a webserver and has VBA modules for uploading it back to the server.
The document generated by the webserver (existing document) is a Word 2003 document, but the document created by the user is either a Word 2003 document or Word 2007+.
Having these limitations in mind, I first created the following method:
string tempsave = //location of user created document;
string savelocation = //location of existing document;
Word.Application objWordOpen = new Word.Application();
Document doclocal = objWordOpen.Documents.Open(tempsave);
Document d1 = objWordOpen.Documents.Open(savelocation);
Word.Range oRange = doclocal.Content;
oRange.Copy();
d1.Activate();
d1.UpdateStyles();
d1.ActiveWindow.Selection.WholeStory();
d1.ActiveWindow.Selection.PasteAndFormat(Word.WdRecoveryType.wdFormatOriginalFormatting);
This is generally working. However, the tables are messed up.
Also, if there is a Page Break, the output is different.
The user created document:
The output - existing document:
Also, at the end of the document a paragraph mark is added, as follows:
The user created document:
The output - existing document:
The page format is also messed up, the output having mirror margins set up.
The user created document:
The output - existing document:
I have also tried using Range.Insert() method and setting the range without copying as described here https://stackoverflow.com/a/54500605/10468231, but I am still having these issues.
I have also tried adding the VBA modules to the document, but there are also Document Variables and other custom properties and I don't want to mess with the file being uploaded to the server.
How do I handle these issues? Both the documents are based on Normal template.
I am open to another suggestion regarding this topic, but I know that .doc files are not handled as easily as .docx format, this is why I think I am stuck with COM Interop.
Thank you.
UPDATE
Based on Macropod code posted by Charles Kenyon, I have managed to copy more of the formatting from the source to target. Still, there is the difference at the page break - the paragraph mark is places on the new page, instead on the same page.
Also, the text is slightly larger, even though the Font Size is the same.
Word.Range oRange;
oRange = Source.Content;
Target.Content.FormattedText = oRange.FormattedText;
LayoutTransfer(Source, Target);
LayoutTransfer method:
private void LayoutTransfer(Document source, Document target)
{
float sPageHght;
float sPageWdth;
float sHeaderDist;
float sFooterDist;
float sTMargin;
float sBMargin;
float sLMargin;
float sRMargin;
float sGutter;
WdGutterStyle sGutterPos;
WdPaperSize lPaperSize;
WdGutterStyleOld lGutterStyle;
int lMirrorMargins;
WdVerticalAlignment lVerticalAlignment;
WdSectionStart lScnStart;
WdSectionDirection lScnDir;
int lOddEvenHdFt;
int lDiffFirstHdFt;
bool bTwoPagesOnOne;
bool bBkFldPrnt;
int bBkFldPrnShts;
bool bBkFldRevPrnt;
WdOrientation lOrientation;
foreach (Word.Section section in source.Sections)
{
lPaperSize = section.PageSetup.PaperSize;
lGutterStyle = section.PageSetup.GutterStyle;
lOrientation = section.PageSetup.Orientation;
lMirrorMargins = section.PageSetup.MirrorMargins;
lScnStart = section.PageSetup.SectionStart;
lScnDir = section.PageSetup.SectionDirection;
lOddEvenHdFt = section.PageSetup.OddAndEvenPagesHeaderFooter;
lDiffFirstHdFt = section.PageSetup.DifferentFirstPageHeaderFooter;
lVerticalAlignment = section.PageSetup.VerticalAlignment;
sPageHght = section.PageSetup.PageHeight;
sPageWdth = section.PageSetup.PageWidth;
sTMargin = section.PageSetup.TopMargin;
sBMargin = section.PageSetup.BottomMargin;
sLMargin = section.PageSetup.LeftMargin;
sRMargin = section.PageSetup.RightMargin;
sGutter = section.PageSetup.Gutter;
sGutterPos = section.PageSetup.GutterPos;
sHeaderDist = section.PageSetup.HeaderDistance;
sFooterDist = section.PageSetup.FooterDistance;
bTwoPagesOnOne = section.PageSetup.TwoPagesOnOne;
bBkFldPrnt = section.PageSetup.BookFoldPrinting;
bBkFldPrnShts = section.PageSetup.BookFoldPrintingSheets;
bBkFldRevPrnt = section.PageSetup.BookFoldRevPrinting;
var index = section.Index;
target.Sections[index].PageSetup.PaperSize = lPaperSize;
target.Sections[index].PageSetup.GutterStyle = lGutterStyle;
target.Sections[index].PageSetup.Orientation = lOrientation;
target.Sections[index].PageSetup.MirrorMargins = lMirrorMargins;
target.Sections[index].PageSetup.SectionStart = lScnStart;
target.Sections[index].PageSetup.SectionDirection = lScnDir;
target.Sections[index].PageSetup.OddAndEvenPagesHeaderFooter = lOddEvenHdFt;
target.Sections[index].PageSetup.DifferentFirstPageHeaderFooter = lDiffFirstHdFt;
target.Sections[index].PageSetup.VerticalAlignment = lVerticalAlignment;
target.Sections[index].PageSetup.PageHeight = sPageHght;
target.Sections[index].PageSetup.PageWidth = sPageWdth;
target.Sections[index].PageSetup.TopMargin = sTMargin;
target.Sections[index].PageSetup.BottomMargin = sBMargin;
target.Sections[index].PageSetup.LeftMargin = sLMargin;
target.Sections[index].PageSetup.RightMargin = sRMargin;
target.Sections[index].PageSetup.Gutter = sGutter;
target.Sections[index].PageSetup.GutterPos = sGutterPos;
target.Sections[index].PageSetup.HeaderDistance = sHeaderDist;
target.Sections[index].PageSetup.FooterDistance = sFooterDist;
target.Sections[index].PageSetup.TwoPagesOnOne = bTwoPagesOnOne;
target.Sections[index].PageSetup.BookFoldPrinting = bBkFldPrnt;
target.Sections[index].PageSetup.BookFoldPrintingSheets = bBkFldPrnShts;
target.Sections[index].PageSetup.BookFoldRevPrinting = bBkFldRevPrnt;
}
}
UPDATE 2
Actually, the page break not remaining in line with paragraph format is not an issue of copying fidelity, but rather an issue of conversion from .doc to .docx. (https://support.microsoft.com/en-us/help/923183/the-layout-of-a-document-that-contains-a-page-break-may-be-different-i)
Maybe someone thought of a method to overcome this.
The following code by Paul Edstein (macropod) may assist you. It will at least give you an idea of the complexities you are facing.
' ============================================================================================================
' KEEP NEXT THREE TOGETHER
' ============================================================================================================
'
Sub CombineDocuments()
' Paul Edstein
' https://www.msofficeforums.com/word-vba/43339-combine-multiple-word-documents.html
'
' Users occasionally need to combine multiple documents that may of may not have the same page layouts,
' Style definitions, and so on. Consequently, combining multiple documents is often rather more complex than
' simply copying & pasting content from one document to another. Problems arise when the documents have
' different page layouts, headers, footers, page numbering, bookmarks & cross-references,
' Tables of Contents, Indexes, etc., etc., and especially when those documents have used the same Style
' names with different definitions.
'
' The following Word macro (for Windows PCs only) handles the more common issues that arise when combining
' documents; it does not attempt to resolve conflicts with paragraph auto-numbering,
' document -vs- section page numbering in 'page x of y' numbering schemes, Tables of Contents or Indexing issues.
' Neither does it attempt to deal with the effects on footnote or endnote numbering & positioning or with the
' consequences of duplicated bookmarks (only one of which can exist in the merged document) and any corresponding
' cross-references.
'
' The macro includes a folder browser. Simply select the folder to process and all documents in that folder
' will be combined into the currently-active document. Word's .doc, .docx, and .docm formats will all be processed,
' even if different formats exist in the selected folder.
'
Application.ScreenUpdating = False
Dim strFolder As String, strFile As String, strTgt As String
Dim wdDocTgt As Document, wdDocSrc As Document, HdFt As HeaderFooter
strFolder = GetFolder: If strFolder = "" Then Exit Sub
Set wdDocTgt = ActiveDocument: strTgt = ActiveDocument.fullname
strFile = Dir(strFolder & "\*.doc", vbNormal)
While strFile <> ""
If strFolder & strFile <> strTgt Then
Set wdDocSrc = Documents.Open(FileName:=strFolder & "\" & strFile, AddToRecentFiles:=False, Visible:=False)
With wdDocTgt
.Characters.Last.InsertBefore vbCr
.Characters.Last.InsertBreak (wdSectionBreakNextPage)
With .Sections.Last
For Each HdFt In .Headers
With HdFt
.LinkToPrevious = False
.range.Text = vbNullString
.PageNumbers.RestartNumberingAtSection = True
.PageNumbers.StartingNumber = wdDocSrc.Sections.First.Headers(HdFt.Index).PageNumbers.StartingNumber
End With
Next
For Each HdFt In .Footers
With HdFt
.LinkToPrevious = False
.range.Text = vbNullString
.PageNumbers.RestartNumberingAtSection = True
.PageNumbers.StartingNumber = wdDocSrc.Sections.First.Headers(HdFt.Index).PageNumbers.StartingNumber
End With
Next
End With
Call LayoutTransfer(wdDocTgt, wdDocSrc)
.range.Characters.Last.FormattedText = wdDocSrc.range.FormattedText
With .Sections.Last
For Each HdFt In .Headers
With HdFt
.range.FormattedText = wdDocSrc.Sections.Last.Headers(.Index).range.FormattedText
.range.Characters.Last.Delete
End With
Next
For Each HdFt In .Footers
With HdFt
.range.FormattedText = wdDocSrc.Sections.Last.Footers(.Index).range.FormattedText
.range.Characters.Last.Delete
End With
Next
End With
End With
wdDocSrc.Close SaveChanges:=False
End If
strFile = Dir()
Wend
With wdDocTgt
' Save & close the combined document
.SaveAs FileName:=strFolder & "Forms.docx", FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
' and/or:
.SaveAs FileName:=strFolder & "Forms.pdf", FileFormat:=wdFormatPDF, AddToRecentFiles:=False
.Close SaveChanges:=False
End With
Set wdDocSrc = Nothing: Set wdDocTgt = Nothing
Application.ScreenUpdating = True
End Sub
' ============================================================================================================
Private Function GetFolder() As String
' used by CombineDocument macro by Paul Edstein, keep together in same module
' https://www.msofficeforums.com/word-vba/43339-combine-multiple-word-documents.html
Dim oFolder As Object
GetFolder = ""
Set oFolder = CreateObject("Shell.Application").BrowseForFolder(0, "Choose a folder", 0)
If (Not oFolder Is Nothing) Then GetFolder = oFolder.Items.Item.Path
Set oFolder = Nothing
End Function
Sub LayoutTransfer(wdDocTgt As Document, wdDocSrc As Document)
' works with previous Combine Documents macro from Paul Edstein, keep together
' https://www.msofficeforums.com/word-vba/43339-combine-multiple-word-documents.html
'
Dim sPageHght As Single, sPageWdth As Single
Dim sHeaderDist As Single, sFooterDist As Single
Dim sTMargin As Single, sBMargin As Single
Dim sLMargin As Single, sRMargin As Single
Dim sGutter As Single, sGutterPos As Single
Dim lPaperSize As Long, lGutterStyle As Long
Dim lMirrorMargins As Long, lVerticalAlignment As Long
Dim lScnStart As Long, lScnDir As Long
Dim lOddEvenHdFt As Long, lDiffFirstHdFt As Long
Dim bTwoPagesOnOne As Boolean, bBkFldPrnt As Boolean
Dim bBkFldPrnShts As Boolean, bBkFldRevPrnt As Boolean
Dim lOrientation As Long
With wdDocSrc.Sections.Last.PageSetup
lPaperSize = .PaperSize
lGutterStyle = .GutterStyle
lOrientation = .Orientation
lMirrorMargins = .MirrorMargins
lScnStart = .SectionStart
lScnDir = .SectionDirection
lOddEvenHdFt = .OddAndEvenPagesHeaderFooter
lDiffFirstHdFt = .DifferentFirstPageHeaderFooter
lVerticalAlignment = .VerticalAlignment
sPageHght = .PageHeight
sPageWdth = .PageWidth
sTMargin = .TopMargin
sBMargin = .BottomMargin
sLMargin = .LeftMargin
sRMargin = .RightMargin
sGutter = .Gutter
sGutterPos = .GutterPos
sHeaderDist = .HeaderDistance
sFooterDist = .FooterDistance
bTwoPagesOnOne = .TwoPagesOnOne
bBkFldPrnt = .BookFoldPrinting
bBkFldPrnShts = .BookFoldPrintingSheets
bBkFldRevPrnt = .BookFoldRevPrinting
End With
With wdDocTgt.Sections.Last.PageSetup
.GutterStyle = lGutterStyle
.MirrorMargins = lMirrorMargins
.SectionStart = lScnStart
.SectionDirection = lScnDir
.OddAndEvenPagesHeaderFooter = lOddEvenHdFt
.DifferentFirstPageHeaderFooter = lDiffFirstHdFt
.VerticalAlignment = lVerticalAlignment
.PageHeight = sPageHght
.PageWidth = sPageWdth
.TopMargin = sTMargin
.BottomMargin = sBMargin
.LeftMargin = sLMargin
.RightMargin = sRMargin
.Gutter = sGutter
.GutterPos = sGutterPos
.HeaderDistance = sHeaderDist
.FooterDistance = sFooterDist
.TwoPagesOnOne = bTwoPagesOnOne
.BookFoldPrinting = bBkFldPrnt
.BookFoldPrintingSheets = bBkFldPrnShts
.BookFoldRevPrinting = bBkFldRevPrnt
.PaperSize = lPaperSize
.Orientation = lOrientation
End With
End Sub
' ============================================================================================================
I used a Template and copied it several times into a new Word Document after editing it.
It worked like this
Word.Range rng = wordDocTarget.Content;
rng.Collapse(Word.WdCollapseDirection.wdCollapseEnd)
rng.FormattedText = wordDocSource.Content.FormattedText
An alternative could also be to insert a whole file to a range / document
rng = wordDoc.Range
rng.Collapse(Word.WdCollapseDirection.wdCollapseEnd)
rng.InsertFile(filepath)

Inserting a VB macro throws Argument not optional error

I am trying to open a Word document from a C# app, insert a macro, run it, then close. The problem I am running into is
Compile Error: Argument not optional
I've been looking at this article but I am not returning anything. Not seeing what I am missing here.
Here is the debugger:
Here is the C# code:
Microsoft.Office.Interop.Word.Application newApp = new Microsoft.Office.Interop.Word.Application();
newApp.Visible = true;
object Unknown = Type.Missing;
var Source = fileName;
var doc = newApp.Documents.Open(Source);
var project = doc.VBProject;
var module = project.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
var macro = "Public Sub DoKbTest()\r\n" +
"MsgBox 'Hello'\r\n" +
"End Sub\r\n" +
"Public sub DoKbTestWithParameter(sMsg As String)\r\n" +
"MsgBox sMsg\r\n" +
"End Sub";
module.CodeModule.AddFromString(macro);
newApp.Run("DoKbTest");
newApp.Quit(ref Unknown, ref Unknown, ref Unknown);
A single quote in VBA denotes a comment. This is what you're generating:
Public Sub DoKbTest()
MsgBox 'Hello'
End Sub
Compare to:
Public Sub DoKbTest()
MsgBox "Hello"
End Sub
Notice how syntax highlighting looks different with double quotes around the string literal.
You're getting that error because the MsgBox function's Message parameter isn't optional, and thus the MsgBox [some comment] instruction isn't a valid function call.
I'd suggest using a verbatim string, it's much cleaner IMO - simply double-up your double quotes to escape them:
var macro = #"
Public Sub DoKbTest()
MsgBox ""Hello""
End Sub
Public Sub DoKbTestWithParameter(ByVal msg As String)
MsgBox msg
End Sub
";
Use DoubleQuotes to enquote the Text to MsgBox.
var macro = "Public Sub DoKbTest()\r\n" +
"MsgBox ""Hello""\r\n" +
"End Sub\r\n" +
"Public sub DoKbTestWithParameter(sMsg As String)\r\n" +
"MsgBox sMsg\r\n" +
"End Sub";

vb.net dataset.load xml file containing string "&"

I'm using a Dataset.Load statement to load a XMl File and on the file I have some tags with the "&" character and this is causing a exception. Are there any way to Load the XML to the dataset or replacing the & for another string.
I tried to do a Replace but when I use StringVar.Replace("&","e") for example when I have "ç" or "ã" strings on the file this chars are replaced for an wrong sequence of chars.
I was trying this
My.Computer.FileSystem.WriteAllText(MyFilePath, My.Computer.FileSystem.ReadAllText(MyFilePath, System.Text.Encoding.UTF8).Replace(" & ", "&"), False, System.Text.Encoding.UTF8)
but it happens that some files has "A&B" or any other combination of letters before and after the "&"
I'll be glad if anyone can help-me.
Thanks
`Hello Guys, I solved my problem. The problem was really #Blorgbeard sayd the Xml File was coming not valid.
Public Shared Function Decompress(text As String) As String
Dim bytes As Byte() = Convert.FromBase64String(text)
Using msi = New MemoryStream(bytes)
Using mso = New MemoryStream()
Using gs = New System.IO.Compression.GZipStream(msi, System.IO.Compression.CompressionMode.Decompress)
Dim bytesAux As Byte() = New Byte(4095) {}
Dim cnt As Integer
While (InlineAssignHelper(cnt, gs.Read(bytesAux, 0, bytesAux.Length))) <> 0
mso.Write(bytesAux, 0, cnt)
End While
End Using
Dim streamReader As StreamReader = New StreamReader(mso, System.Text.Encoding.UTF8, True)
Dim XmlDoc As String
mso.Seek(0, SeekOrigin.Begin)
XmlDoc = streamReader.ReadToEnd
Return XmlDoc
End Using
End Using
End Function`
this is what I did to get and return the string containing the correct XML data to be write to file.

How to determine what "Ne" port the Adobe PDF printer is on?

How can I detect what port (Ne01:, Ne02:, Ne99: etc) the printer is on?
Computers (WinXP) here at BigCorp have Adobe Acrobat (version 7.0 Pro) installed which gives a virtual printer named "Adobe PDF". If you print an Excel (2003) workbook to pdf while recording a macro, the printer's full name is "Adobe PDF on Nexx:" where xx is a double digit.... and differs depending on what computer you try.
I have written a C# console app using the Excel.Interop (I strongly discourage anyone else from starting down this road to hell) that opens a series of spreadsheets. It runs a macro in each one, saves, prints is as a pdf, then moves the pdf to a reports folder on a shared drive.
The problem I face is that every install of Acrobat seems to pick a random port number for the PDF printer... and I can't figure out how to get it.
So far I have tried using the Win32_Printer class like so
var searcher = new ManagementObjectSearcher( #"SELECT * FROM Win32_Printer" );
foreach ( ManagementObject printer in searcher.Get() )
{
if ( Regex.IsMatch( printer["Name"].ToString(), #"(adobe|pdf)", RegexOptions.IgnoreCase ) )
{
//printer["Name"]; => "Adobe PDF"
//printer["PortName"] => "my documents/*.pdf"
foreach ( PropertyData pd in printer.Properties )
{
Console.WriteLine(string.Format("{0}, {1}", pd.Name, pd.Value));
}
break;
}
}
I also poked around in the System.Drawing.Printing class. The PrinterSettings.InstalledPrinters will give you the name of the printer "Adobe PDF" but I can't figure out how to get the port info.
If I pass just "Adobe PDF" to the excel interop PrintOut() method it sometimes works and sometimes fails with "Document failed to print"... I cannot figure out why.
If I pass a hardcoded "Adobe PDF on Ne0x:" with an appropriate x value it works every time.
If I try every possible variation, Excel helpfully prints to the default printer. I do not have the option of changing the default printer (security policy restriction)
Can anyone point me to code that correctly pulls the printer port?
Here's what I ended up doing
using Microsoft.Win32;
...
var devices = Registry.CurrentUser.OpenSubKey( #"Software\Microsoft\Windows NT\CurrentVersion\Devices" ); //Read-accessible even when using a locked-down account
string printerName = "Adobe PDF";
try
{
foreach ( string name in devices.GetValueNames() )
{
if ( Regex.IsMatch( name, printerName, RegexOptions.IgnoreCase ) )
{
var value = (String)devices.GetValue( name );
var port = Regex.Match( value, #"(Ne\d+:)", RegexOptions.IgnoreCase ).Value;
return printerName + " on " + port;
}
}
}
catch
{
throw;
}
Last time I used Acrobat it always used to install itself on LPT1: thus avoiding the problem. But I think you have to grovel around in the registry, HKCU\Software\Microsoft\Windows NT\CurrentVersion\Devices has them.
As you discovered you have to query the registry, the is the way I used [in VBA], which I got from Chip Pearson's great Excel site:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' modListPrinters
' By Chip Pearson, chip#cpearson.com www.cpearson.com
' Created 22-Sept-2012
' This provides a function named GetPrinterFullNames that
' returns a String array, each element of which is the name
' of a printer installed on the machine.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Const HKEY_CURRENT_USER As Long = &H80000001
Private Const HKCU = HKEY_CURRENT_USER
Private Const KEY_QUERY_VALUE = &H1&
Private Const ERROR_NO_MORE_ITEMS = 259&
Private Const ERROR_MORE_DATA = 234
Private Const REG_SZ = 1
Private Declare Function RegOpenKeyEx Lib "advapi32" _
Alias "RegOpenKeyExA" ( _
ByVal hKey As Long, _
ByVal lpSubKey As String, _
ByVal ulOptions As Long, _
ByVal samDesired As Long, _
phkResult As Long) As Long
Private Declare Function RegEnumValue Lib "ADVAPI32.DLL" _
Alias "RegEnumValueA" ( _
ByVal hKey As Long, _
ByVal dwIndex As Long, _
ByVal lpValueName As String, _
lpcbValueName As Long, _
ByVal lpReserved As Long, _
lpType As Long, _
lpData As Byte, _
lpcbData As Long) As Long
Private Declare Function RegCloseKey Lib "ADVAPI32.DLL" ( _
ByVal hKey As Long) As Long
Public Function GetPrinterFullNames() As String()
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' GetPrinterFullNames
' By Chip Pearson, chip#cpearson.com, www.cpearson.com
' Returns an array of printer names, where each printer name
' is the device name followed by the port name. The value can
' be used to assign a printer to the ActivePrinter property of
' the Application object. Note that setting the ActivePrinter
' changes the default printer for Excel but does not change
' the Windows default printer.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim Printers() As String ' array of names to be returned
Dim PNdx As Long ' index into Printers()
Dim hKey As Long ' registry key handle
Dim Res As Long ' result of API calls
Dim Ndx As Long ' index for RegEnumValue
Dim ValueName As String ' name of each value in the printer key
Dim ValueNameLen As Long ' length of ValueName
Dim DataType As Long ' registry value data type
Dim ValueValue() As Byte ' byte array of registry value value
Dim ValueValueS As String ' ValueValue converted to String
Dim CommaPos As Long ' position of comma character in ValueValue
Dim ColonPos As Long ' position of colon character in ValueValue
Dim M As Long ' string index
' registry key in HCKU listing printers
Const PRINTER_KEY = "Software\Microsoft\Windows NT\CurrentVersion\Devices"
PNdx = 0
Ndx = 0
' assume printer name is less than 256 characters
ValueName = String$(256, Chr(0))
ValueNameLen = 255
' assume the port name is less than 1000 characters
ReDim ValueValue(0 To 999)
' assume there are less than 1000 printers installed
ReDim Printers(1 To 1000)
' open the key whose values enumerate installed printers
Res = RegOpenKeyEx(HKCU, PRINTER_KEY, 0&, _
KEY_QUERY_VALUE, hKey)
' start enumeration loop of printers
Res = RegEnumValue(hKey, Ndx, ValueName, _
ValueNameLen, 0&, DataType, ValueValue(0), 1000)
' loop until all values have been enumerated
Do Until Res = ERROR_NO_MORE_ITEMS
M = InStr(1, ValueName, Chr(0))
If M > 1 Then
' clean up the ValueName
ValueName = Left(ValueName, M - 1)
End If
' find position of a comma and colon in the port name
CommaPos = InStr(1, ValueValue, ",")
ColonPos = InStr(1, ValueValue, ":")
' ValueValue byte array to ValueValueS string
On Error Resume Next
ValueValueS = Mid(ValueValue, CommaPos + 1, ColonPos - CommaPos)
On Error GoTo 0
' next slot in Printers
PNdx = PNdx + 1
Printers(PNdx) = ValueName & " on " & ValueValueS
' reset some variables
ValueName = String(255, Chr(0))
ValueNameLen = 255
ReDim ValueValue(0 To 999)
ValueValueS = vbNullString
' tell RegEnumValue to get the next registry value
Ndx = Ndx + 1
' get the next printer
Res = RegEnumValue(hKey, Ndx, ValueName, ValueNameLen, _
0&, DataType, ValueValue(0), 1000)
' test for error
If (Res <> 0) And (Res <> ERROR_MORE_DATA) Then
Exit Do
End If
Loop
' shrink Printers down to used size
ReDim Preserve Printers(1 To PNdx)
Res = RegCloseKey(hKey)
' Return the result array
GetPrinterFullNames = Printers
End Function
I then use this function to get the PDF printer name:
Public Function FindPDFPrinter() As String
'this function finds the exact printer name for the Adobe PDF printer
Dim Printers() As String
Dim N As Integer
FindPDFPrinter = ""
Printers = GetPrinterFullNames()
For N = LBound(Printers) To UBound(Printers)
If InStr(1, Printers(N), "PDF") Then
FindPDFPrinter = Printers(N)
End If
Next N
End Function
You then set Application.ActivePrinter to that String.
And if you really just need the port, you can pull it off of the end of the string.

Categories