I have been trying for days now to find a solution for my problem.
I think the problem is simple but it won't work on my end and I'm not the best-experienced developer around the world. So Im using VB.net with CEFSharp and want to deactivate my browser to open links in new windows, I want that nothing happens then because I only have a web-based application which is included in Form1.
So I already tried to translate some C# code:
Public Class BrowserLifeSpanHandler
Inherits ILifeSpanHandler
Public Function OnBeforePopup(ByVal browserControl As IWebBrowser, ByVal browser As IBrowser, ByVal frame As IFrame, ByVal targetUrl As String, ByVal targetFrameName As String, ByVal targetDisposition As WindowOpenDisposition, ByVal userGesture As Boolean, ByVal popupFeatures As IPopupFeatures, ByVal windowInfo As IWindowInfo, ByVal browserSettings As IBrowserSettings, ByRef noJavascriptAccess As Boolean, <Out> ByRef newBrowser As IWebBrowser) As Boolean
newBrowser = Nothing
Return True
End Function
But there are 2 errors. The first one is with the ILifeSpanHandler.
It says that classes can only inherit from other classes. Was it wrong to put the code snippet over the End Class of my Form1?
The second error is at <Out> ByRef newBrowser As IWebBrowser.
Visual Studio says that type "Out" isnt defined. So what to put in there?
My main question: What do I have to change & why? :)
Thanks.
Related
I am new to VB and is working on VB6 to VB.net migration. There is one API call which appends a prefix in temporary file name.
I have added the dll as
<DllImport("kernel32")> _
Private Shared Function GetTempFileName(ByVal lpszPath As String, ByVal lpPrefixString As String, ByVal wUnique As Long, ByVal lpTempFileName As String) As Long
End Function
When I am calling this:
test = GetTempFileName(My.Application.Info.DirectoryPath, Prefix, 0, m_sTempfile)
It throws an exception:
An unhandled exception of type 'System.AccessViolationException' occurred in Forum.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I tried using Path.GetTempFileName() but I might need to perform several manipulation to get the file name prefixed with specific word and located to specific location.
I crossed checked the values and they are NOT bad data.
I tried mutiple resolutions, but none of it worked.
Can someone help in this? Thanks in advance!
Pinvoke declarations need to be rewritten when you move them to VB.NET. Many differences, like Long needs to be Integer and if the winapi function returns a string then you need to use StringBuilder instead of String. Required because String is an immutable type.
Proper declaration is:
<DllImport("kernel32", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function GetTempFileName(ByVal lpszPath As String, _
ByVal lpPrefixString As String, _
ByVal wUnique As Integer, _
ByVal lpTempFileName As StringBuilder) As Integer
End Function
And a proper call looks like:
Dim buffer As New StringBuilder(260)
If GetTempFileName("c:\temp", "xyz", 0, buffer) = 0 Then
Throw New System.ComponentModel.Win32Exception()
End If
Dim filename = buffer.ToString()
The pinvoke.net website tends to be a half-decent resource for pinvoke declarations. Not for this one though, the VB.NET version is pretty fumbled.
I am trying to get an FTP Download operation to work with VBA Excel (on Excel 2013 x64, Windows 7 SP1 x64). I found some code that maps to the WinInet API and I can successfully upload files using the PutFile function but I am looking to get a GetFile function to work as well.
To get working what I have so far, I used the following: second answer here, and this link. I've been mostly using the second answer from SO to get PutFile to work. I had to make some changes to the original code to make it compatible with 32 bit and 64 bit systems.
You can see my progress here.
What I am looking to do is make an easy to use Sub that calls this declaration:
Private Declare Function FtpGetFile Lib "WinInet" Alias "FtpGetFileA" (ByVal hFtp As Long, ByVal lpszRemoteFile As String, ByVal lpszNewFile As String, ByVal fFailIfExists As Long, ByVal dwFlagsAndAttributes As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long
I.E. a Sub like this:
Public Sub GetFile(RemoteFilename As String, LocalFilename As String)
If FtpGetFile(' what arguments do I put here ') = 0 Then
Err.Raise vbObjectError + 1, , LastError
End If
End Sub
I am struggling because I am not very familiar with the WinInet API and am having difficulty parsing the required arguments and what are the appropriate variables to pass for those arguments.
This should get you started on the right path, based on the example provided.
In your class module:
Public Sub GetFile(RemoteFilename As String, NewFilename As String)
If FtpGetFile(m_hFtp, RemoteFilename, NewFilename, False, 0, FTP_TRANSFER_TYPE_BINARY, 0) = 0 Then
Err.Raise vbObjectError + 1, , LastError
End If
End Sub
How to call it:
Sub DownloadFile()
Dim ftp As New CFtp
ftp.Connect "serverAddress", "username", "password"
ftp.GetFile "nameOfFileOnServer.txt", "C:\SomePath\nameOfNewFile.txt"
ftp.Disconnect
End Sub
The parameters specify some attributes to associate with the downloaded file. For example, fFailIfExists is a Boolean that describes whether or not to throw an exception if it is trying to overwrite a local file that already exists. The other flags specify attributes to attach to the file it creates.
How can I extract items from other application's gridview? The class name of the control is TStringGrid.
I can get the handle of the TStringGrid window with FindWindowEx using these declarations:
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, _
ByVal childAfter As IntPtr, _
ByVal lclassName As String, _
ByVal windowTitle As String) As IntPtr
End Function
code:
Dim TheMainForm As Integer = FindWindow("form", "fname")
Dim GV As Integer = FindWindowEx(TheMainForm, 0, "TStringGrid", "")
How can I extract the items from GV (TStringGrid handle)?
(I have to finish this project by tomorrow.)
A Delphi string grid is not a windows control. It's a custom Delphi control. As such it doesn't respond to windows messages asking for its content. Without the source of the app you would need to reverse engineer the app to work out where the content is stored.
Realistically the most effective way to do this will be to inject a thread into the target application. That thread can then do the work of reading the information and can then use some IPC to get the data back to your VB process.
In order to do this you will, ideally, need:
Knowledge of the exact version of Delphi used to build the app.
A deep understanding of the Delphi compiler and RTL.
The Delphi VCL source code for TStringGrid.
I've no idea how you'll be able to synchronize your reading thread with the Delphi app.
Anyway, whilst what you ask for is, in theory possible, in reality it is completely impractical. The sensible solution is to ask the authors of the Delphi program to provide an automation interface.
Currently, Smart Indent in VS 2010 is giving me lots of headaches. Everytime I try to put each parameter of a Sub or a Function into one line like
Private Function Foo (ByVal a As String, _
ByVal i As Integer)
I get things like
Private Function Foo (ByVal a As String, _
ByVal i As Integer)
Can you point me to some extension/add-on/configuration to pretty print VB code?
Did you try this?
Private Function Foo( _
ByVal a As String, _
ByVal i As Integer)
Breaking the line before the first parameter puts each of your parameters on a seperate line and treats them all identically rather than making an exception (not a pun) of the first one.
I have code that needs to run on both Excel 2003 and Excel 2007, and there are a few spots where changes in the versions cause the code to halt. I tried separating these lines out with If-Else statements, but the code won't compile on either because it doesn't recognize the code used for the other. Is there any way I could tell one version to ignore a block of code, similar to a C or C++-style #ifdef, in VBA?
This is a good starting point, but it won't work with the version of Excel that its running on, since that can only be figured out at run-time, not compile time.
If you need to branch your code based on information only discoverable at run time you might consider late binding as a solution. There are two ways you can sneak around version problems.
The first way can be used if you need to Access a property or method that only exists in certain versions, you can use CallByName. The advantage of call by name is that it allows you to preserve early binding (and intellisense) for your objects as much as possible.
To give an example, Excel 2007 has a new TintAndShade property. If you wanted to change the color of a range, and for Excel 2007 also ensure TintAndShade was set to 0 you would run into trouble because your code won't compile in Excel 2003 which does not have TintAndShade as a property of the range object. If you access the property that you know is not in all versions using CallByName, you code will compile in all versions fine, but only run in the versions you specify. See below:
Sub Test()
ColorRange Selection, Excel.Application.version, 6
End Sub
Sub ColorRange(rng As Excel.Range, version As Double, ParamArray args() As Variant)
With rng.Interior
.colorIndex = 6
.Pattern = xlSolid
If version >= 12# Then
'Because the property name is stored in a string this will still compile.
'And it will only get called if the correct version is in use.
CallByName rng.Interior, "TintAndShade", VbLet, 0
End If
End With
End Sub
The second way is for classes that have to be instantiated via "New" and don't even exist in old versions. You won't run into this problem with Excel, but I will give a quickie demo so you can see what I mean:
Imagine that you wanted to do File IO, and for some bizarre reason not all of the computers had the Microsoft Scripting Runtime on them. But for some equally bizarre reason you wanted to make sure it was used whenever it was available. If set a reference to it and use early binding in your code, the code won't compile on systems that don't have the file. So you use late binding instead:
Public Sub test()
Dim strMyString As String
Dim strMyPath As String
strMyPath = "C:\Test\Junk.txt"
strMyString = "Foo"
If LenB(Dir("C:\Windows\System32\scrrun.dll")) Then
WriteString strMyPath, strMyString
Else
WriteStringNative strMyPath, strMyString
End If
End Sub
Public Sub WriteString(ByVal path As String, ByVal value As String)
Dim fso As Object '<-Use generic object
'This is late binding:
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CreateTextFile(path, True, False).Write value
End Sub
Public Sub WriteStringNative(ByVal path As String, ByVal value As String)
Dim lngFileNum As Long
lngFileNum = FreeFile
If LenB(Dir(path)) Then Kill path
Open path For Binary Access Write Lock Read Write As #lngFileNum
Put #lngFileNum, , value
Close #lngFileNum
End Sub
There is a comprehensive list of all Adds and Changes to Excel Object Model since 2003:
http://msdn.microsoft.com/en-us/library/bb149069.aspx
For changes between 1997 and 2000 go here:
http://msdn.microsoft.com/en-us/library/aa140068(office.10).aspx
Yes it is possible to do conditional compilation in Excel VBA. Below is a brief resource and some example code:
Conditional Compilation
#If Win32 Then
' Profile String functions:
Private Declare Function WritePrivateProfileString Lib "KERNEL32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long
Private Declare Function GetPrivateProfileString Lib "KERNEL32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As Any, ByVal lpKeyName As Any, ByVal lpDefault As Any, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
#Else
' Profile String functions:
Private Declare Function WritePrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Integer
Private Declare Function GetPrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As Any, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer
#End If
Can you post the offending lines of code?
If it is a constant like vbYes or xlFileFormat or whatever, use the corresponding numeric value.
Show me what you got, I'll see if I can refactor it.
Bill