I'm having trouble implementing an extended hex value onto my project. When I type &H000007F0 into my Visual Basic project, Visual Studio goes and shortens it to &H7F0. In a normal situation, that would be fine but I need the preceding 0's to be included as a parameter for a function on an API.
I've tried creating it as a string Dim MastID As String = "000007F0" and then converting to a hex Convert.ToUInt32(MastID, 16), but that didn't work like I thought it would. Are there any other methods I can try or a VS17 setting I can turn off/on that will allow me to have the full &H000007F0?
I'm doing this to try to connect to a slave device on a CAN bus. I'm using an API that has it's own functions to control the CAN device and initialize a CAN channel. If I am able to pass the extended ID, &H000007F0, then the API would initialize the CAN channel with those parameters.
Parameters being set for slave data:
SlaveData.BroadcastID = &H18DAA1E1
SlaveData.MasterID = &H7F0
SlaveData.SlaveID = &H7F2
SlaveData.IncrementalIdUsed = False
Function being used:
Public Shared Function Connect(
ByVal Handle As UInt32,
ByVal Mode As Byte,
) As Result ' Returns no errors
End Function
Analyzing the CAN BUS, the device ID being used is 7F0h, therefore the slave device does not respond with an acknowledge message. It does however work when I send the same function with the extended master ID my making my own byte array.
As has been pointed out you do not need the leading zeros. Here is some food for thought...
Dim foo As UInt32 = &H7F0 'note missing 0's
' or
Dim provider As Globalization.CultureInfo = Globalization.CultureInfo.CurrentCulture
Dim styles As Globalization.NumberStyles = Globalization.NumberStyles.HexNumber
Dim bar As UInt32
Dim s As String = "000007F0" 'note leading 0's
If UInt32.TryParse(s, styles, provider, bar) Then
If foo = bar Then
Stop ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
End If
End If
Related
I have a report done via VS2008 SSRS that is uploaded to my Reporting Services Server, that report is called when the event GenerateReport is called (on button click)
Now, I have the following code:
Public Shared Dim gruposVolTotal As New System.Collections.HashTable()
Public Shared Dim gruposSeleccion As New System.Collections.HashTable()
Public Shared Dim gruposModVenta As New System.Collections.HashTable()
Dim grupoActual as String = ""
Public Shared Dim acumuladoSeleccion as Double = 0
Public Shared Dim acumuladoVolTotal as Double = 0
Public Shared Dim acumuladoModVenta as Double = 0
Public Shared Dim acumuladoAnterior as Double = 0
Function Acumulador(ByVal MiGrupo as String, ByVal value as Double, ByVal Campo as String) As Double
If (GrupoActual <> MiGrupo) Then
If (Campo = "ModVenta") then
If (not gruposModVenta.Contains(MiGrupo)) then
acumuladoModVenta =acumuladoModVenta + value
gruposModVenta.Add(MiGrupo,acumuladoModVenta )
Return acumuladoModVenta
Else
Return gruposModVenta(MiGrupo)
End If
End If
If (Campo = "RunningValue") then
acumuladoVolTotal=acumuladoVolTotal + value
If (not gruposVolTotal.Contains(MiGrupo)) then
acumuladoAnterior = acumuladoVolTotal + acumuladoAnterior
gruposVolTotal.Add(MiGrupo, acumuladoAnterior)
End If
Return gruposVolTotal(MiGrupo)
End If
If (Campo = "VolumenSeleccion") then
If(not gruposSeleccion.Contains(MiGrupo)) then
acumuladoSeleccion=acumuladoSeleccion + value
gruposSeleccion.Add(MiGrupo, acumuladoSeleccion)
Return acumuladoSeleccion
Else
return gruposSeleccion(MiGrupo)
End If
End If
End If
End Function
What is the problem with this:
If you execute this on VS2008 the results are correct if I change pages (remember on VS2008) the elements persists and that is good.
If you execute this via web application, the first time will execute correctly but the second time if you choose different parameters on the report the values will stay as the 1st time you execute it.
This is because the variables and elements of the hashtables are saved in session so until I dont close the webpage and enter it again the values of these Hashtables and variables will stay the same after the first time you execute it.
If you change the scope of the variables and Hashtables to public, private or directly dim (private) each request (change of pages aka break page) will reset the value of the variables and hashtables.
So the Idea is to utilize the code I posted but what Im asking if is there any way to reset or clear the elements of the hashtables each time I call the report and change the parameters.
I saw in a forum that another user created a new hashtable for each request but those Hashtables wont be garbage collected and that means a lot of memory usage.
Let me know if you need more information.
EDIT:
You change the pages via ReportViewer Control.
I tried using the following code:
Protected Overrides Sub OnInit()
gruposVolTotal.Clear()
gruposSeleccion.Clear()
gruposModVenta.Clear()
grupoActual = ""
acumuladoSeleccion = 0
acumuladoVolTotal = 0
acumuladoModVenta = 0
acumuladoAnterior = 0
End Sub
But it seems it deletes it for every change of page and not each time I open the report.
I'm trying to compare 2 strings (KeyCode and SerialN)
I've tried a bunch of diferente aproaches... but as you can see in my print screen neither = or Equals work.
Can you tell me what is wrong?
Private Function VerificaKeyCode(SerialN As String) As Boolean
Dim snEsq As Integer
Dim snDir As Integer
Dim KeyCode As String
Dim buffer As String
Dim ind As Short
VerificaKeyCode = False
buffer = Space(255)
For ind = 1 To 5
'UPGRADE_WARNING: App property App.EXEName has a new behavior. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6BA9B8D2-2A32-4B6E-8D36-44949974A5B4"'
GetPrivateProfileString(My.Application.Info.AssemblyName, "HD" & ind, "", buffer, Len(buffer), My.Application.Info.DirectoryPath & "\ServerHD.ini")
KeyCode = Trim(buffer)
If KeyCode <> "" Then
VerificaKeyCode = KeyCode.Equals(SerialN)
VerificaKeyCode = CBool(KeyCode = SerialN)
If VerificaKeyCode Then Exit Function
End If
Next ind
End Function
Edit
Aparently there is an empty char in the string, I need to remove it somehow
The expressions in your watch window are stale as indicated by the disabled color and the presence of the Refresh/Recycle icon. Click the icon and the expression will be re-evaluated and the result updated:
Mimicking what you have, notice the first expression is stale and wrong. The second has been refresh/reevaluated and reports the correct result. As soon as you execute a line of code, the watch expressions will be marked as stale/not updated.
A better way to return a function with NET is to use a local variable and Return it. The local var allow you to easily view the result by hovering the mouse:
A variable can go out of scope, but it can't be stale.
Edit 4 or 5 reveals that while the watch expressions are stale, so what we see in the pic neither proves nor disproves that the strings do not match, this is apparently a VB6 -> .NET refurb (notice the 102 warnings).
We cant see the declaration for GetPrivateProfileString but the usage is at least suboptimal.
<DllImport("kernel32.dll", SetLastError:=True)>
Shared Function GetPrivateProfileString(appname As String,
keyname As String, def As String,
sbuffer As StringBuilder,
nSize As Int32,
strFile As String) As Integer
End Function
Note that it is a Function; it returns the number of chars read into the buffer. Rather than Trim which will not remove NUL, the return should be used (if not a stringbuilder) to get the number of characters specified. If you use a string buffer, trim to the number of characters read:
Dim n As Int32 = GetPrivateProfileString(...)
KeyCode = buffer.Substring(0, n)
StringBuilder should do that for you:
Dim buffer As New StringBuilder(255)
...
Dim n As Int32 = GetPrivateProfileString(..., buffer, buffer.Capacity)
KeyCode = buffer.ToString()
You can still check the function return against the size of the string.
You could skip GetPrivateProfileString entirely and read the file yourself with a stream reader. It should be faster than PInvoke, but at the least, less convoluted to use.
I want to send a string Message from .net Application A and Receive the message from the Application B and here's the code:
-------- Application A
Private Const RF_TESTMESSAGE As Integer = &HA123
Public Structure MyData
Public M As String
Public I As Integer
End Structure
Public Function SendTest()
Dim Data As New MyData
Data.M = "QWERTY"
Data.I = 15
Dim P As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Data))
Marshal.StructureToPtr(Data, P, False)
Dim Hdl As New IntPtr(11111) 'While 11111 is the WndHD for the application B for testing
SendMessage(Hdl, RF_TESTMESSAGE, IntPtr.Zero, P)
End Function
------- Application B
Private Const RF_TESTMESSAGE As Integer = &HA123
Public Structure MyData
Public M As String
Public I As Integer
End Structure
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = RF_TESTMESSAGE Then
Dim A = DirectCast(m.GetLParam(GetType(MyData)), MyData)
MsgBox(A.M)
MsgBox(A.I)
Marshal.FreeHGlobal(m.LParam)
End If
MyBase.WndProc(m)
End Sub
The application B always receive the message, but unable to convert the point lParam to valid MyData Structure, and sometime raise access violation, sometime no error ....
Please advice.
The problem is that you're not properly marshalling the data between the two applications. You are allocating memory in one application, and then passing a pointer to that memory to a second application. But because application's have private memory spaces and cannot read each other's memory, that pointer is useless to the second application.
Depending on what it points to in that application's memory space, it might be triggering an access violation, or just not working properly.
Perhaps you're confused by the naming of the AllocHGlobal and FreeHGlobal functions. Contrary to what first impressions might suggest, they do not actually allocate and free global memory. At least not memory that is globally accessible to all processes running on a machine. The name comes from the Windows HGLOBAL data type, which used to mean exactly this back in the days of 16-bit Windows, where all applications did share a common memory space and could read each others' memory. But that is no longer the case in modern 32-bit Windows. The names were retained for backwards compatibility reasons. HGLOBAL and HLOCAL mean effectively the same thing nowadays. More on the nitty gritty details is available on MSDN. But that's mostly a curiosity. You don't need to know and understand all of it to get the code working correctly.
The point is that all AllocHGlobal does is allocate memory from the process's default heap, readable only to that process. Hence the need to marshal the memory across processes, making it accessible from the other one receiving the message. Doing this manually is, of course, an option. But not a very good one. It's tricky to get right, and there's little point. Like Tim's comment hints at, the easier option is to use the WM_COPYDATA message, which does the marshalling for you. When you use this message, the data you want to share is packaged in a COPYDATASTRUCT structure.
You can keep most of your existing code to allocate memory, you just need to replace your custom RF_TESTMESSAGE window message with WM_COPYDATA. Sample code, including the necessary structure definition, is available over on the pinvoke website.
Something like this (warning—untested and uncompiled):
Private Const WM_COPYDATA As Integer = &H004A
<StructLayout(LayoutKind.Sequential)> _
Public Structure COPYDATASTRUCT
Public dwData As IntPtr
Public cdData As Integer
Public lpData As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure MyData
Public M As String
Public I As Integer
End Structure
Public Function SendTest()
' Create your data structure, MyData, and fill it.
Dim data As New MyData
data.M = "QWERTY"
data.I = 15
Dim pData As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(data))
Marshal.StructureToPtr(data, pData, False)
' Create the COPYDATASTRUCT you'll use to shuttle the data.
Dim copy As New COPYDATASTRUCT
copy.dwData = IntPtr.Zero
copy.lpData = pData
copy.cbData = Marshal.SizeOf(data)
Dim pCopy As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(copy))
Marshal.StructureToPtr(copy, pCopy, False)
' Send the message to the other application.
SendMessage(New IntPtr(11111), WM_COPYDATA, IntPtr.Zero, pCopy)
' Free the memory we allocated
' (This works because SendMessage is synchronous, and does not
' return until the other application has finished processing
' the data that you have sent it. That also means that the
' other application should not and cannot free the memory.
' If it needs it after processing the message, it needs to
' make a local copy.)
Marshal.FreeHGlobal(pCopy)
Marshal.FreeHGlobal(pData)
End Function
If you decide not to go the easy route using WM_COPYDATA and instead marshal the data yourself, you need to make sure to call the RegisterWindowMessage function (if you are not doing so already in code I can't see) to ensure that the ID of your custom window message is unique.
The title is to make this easy to find for others having this error. I'm new to Threading, so this is really giving me heck. I'm getting this runtime error that crashed Cassini. This is code that I'm maintaining originally developed as a website project in VS 2003 and converted to a VS 2008 website project.
Important Info:
The number of objects in the manualEvents array is 128 in this case.
products is an array of Strings
Need to support .NET 2.0
For Each product As String In products
If Not product.Trim().ToUpper().EndsWith("OBSOLETE") Then
calls += 1
End If
Next
Dim results(calls - 1) As DownloadResults
'Dim manualEvents(calls - 1) As Threading.ManualResetEvent '128 objects in this case.
Dim manualEvents(0) As Threading.ManualResetEvent
manualEvents(0) = New Threading.ManualResetEvent(False)
'NOTE: I don't think this will work because what is not seen here, is that
' this code is being used to populate and cache a long list of products,
' each with their own category, etc. Am I misunderstanding something?
'initialize results structures
'spawn background workers
calls = 0
For Each product As String In products
If Not product.Trim().ToUpper().EndsWith("OBSOLETE") Then
Dim result As New DownloadResults
'manualEvents(calls) = New Threading.ManualResetEvent(False)
'Moved above For Each after declaration of variable
result.params.product = product
result.params.category = docType
'result.ManualEvent = manualEvents(calls)
result.ManualEvent = manualEvents(0)
result.Context = Me._context
results(calls) = result
Threading.ThreadPool.QueueUserWorkItem(AddressOf ProcessSingleCategoryProduct, results(calls))
Threading.Interlocked.Increment(calls) 'Replaces below incrementation
'calls += 1
End If
Next
Threading.WaitHandle.WaitAll(manualEvents) 'CRASHES HERE
Thread Helper Function (for the sake of completion)
Public Shared Sub ProcessSingleCategoryProduct(ByVal state As Object)
Dim drs As DownloadResults = CType(state, DownloadResults)
Dim adc As New cADCWebService(drs.Context)
drs.docs = adc.DownloadADC(drs.params.category, drs.params.product)
drs.ManualEvent.Set()
End Sub
You don't need an array of 128 manual events to check for completion of all 128 threads.
Create only one manual reset event and a plain integer starting at 128. Decrement that integer using Interlocked.Decrement at the end of ProcessSingleCategoryProduct, and only signal the event when the count reaches zero:
if (Interlocked.Decrement(ByRef myCounter) = 0) myEvent.Set();
Then declare only one Threading.ManualResetEvent as opposed to an array of them, and you can call WaitOne instead of WaitAll on it, and you are done.
See also usr's comment for an easier alternative in case you have .NET 4.
I am trying to do 1 of two things, preference number 1:
Turn on the Live View using VB.NET and the Canon EDSDK 2.5.2 and render the live output in a Windows Forms application. Currently I am trying to put it to a picture box; however, I am open to suggestions for sure.
The second option would be to at least turn on the Live View and have it stream via the Video output on the camera to a monitor.
I really want to accomplish the first though! Below is my current codebase, help!
Private Sub btnStartLiveView_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStartLiveView.Click
Dim err As Integer = EDS_ERR_OK
Dim prop As Integer = EdsEvfOutputDevice.kEdsEvfOutputDevice_PC
Dim proptype As Integer = EDSDKTypes.kEdsPropID_Evf_OutputDevice
'// Stock the property.'
Dim wkIntPtr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(prop))
Marshal.StructureToPtr(prop, wkIntPtr, False)
'send property/command to the camera'
EdsSetPropertyData(model.getCameraObject(), proptype, 0, Marshal.SizeOf(prop), prop)
Dim stream As IntPtr
Dim outMemoryRef As IntPtr
Dim evfImage As IntPtr
err = EdsCreateMemoryStream(0, stream)
If err = EDS_ERR_OK Then
err = EdsCreateImageRef(stream, outMemoryRef) '(stream, evfImage)'
Else
Dim str As String = Hex(err)
MessageBox.Show(str)
End If
If err = EDS_ERR_OK Then
err = EdsDownloadEvfImage(model.getCameraObject(), evfImage)
Else
Dim str As String = Hex(err)
MessageBox.Show("&H" & str & "L") ' Shows &H2CL which = ERR_FILE_FORMAT_NOT_RECOGNIZED'
End If
' Get the Incidental Data of the Image'
If err = EDS_ERR_OK Then
Dim zoom As UInt32
Dim point As IntPtr
EdsGetPropertyData(outMemoryRef, kEdsPropID_Evf_ZoomPosition, 0, Marshal.SizeOf(zoom), zoom)
EdsGetPropertyData(outMemoryRef, kEdsPropID_Evf_ZoomPosition, 0, Marshal.SizeOf(point), point)
Else
'MessageBox.Show(err.ToString())'
End If
Dim buffer(Marshal.SizeOf(stream)) As Byte
Dim mStream As System.IO.Stream = New System.IO.MemoryStream(Marshal.SizeOf(stream))
Dim gcTime As GCHandle = GCHandle.Alloc(0, GCHandleType.Pinned)
Dim pTime As IntPtr = gcTime.AddrOfPinnedObject()
Marshal.Copy(stream, buffer, 0, Marshal.SizeOf(stream))
mStream.Write(buffer, 0, Marshal.SizeOf(stream))
Me.PictureBox1.Image = Image.FromStream(mStream)
EdsRelease(stream)
End Sub
I was the one who originally posted this question. I see that there are others here who are still seeking the answer. I have posted the solution that we finally came up with over on my blog at http://www.overridepro.com/2009/06/28/canon-sdk-live-view/ .
Here's a .vb file in which I define class Camera which lets you do top level things like
Dim camera as New Camera
camera.EstablishSession()
camera.TakePicture("C:\path\to\save.jpg")
camera.StartLiveView(me.LiveViewPictureBox)
camera.StopLiveView()
camera.FlushTransferQueue()
I think you may find it useful:
<snip>
Over the years I've received multiple emails for updates to this block of code, which is on GitHub as open source:
http://github.com/superjoe30/Camlift-Controller
The Camera class is in slnCamliftController / src / Camera.vb
Some of this code is embarrassingly terrible. For example, in order to get it to work for the 5D and 7D camera, I have to create a program that initializes the SDK and then crashes on purpose. Terrible! I know! This is found in Klugesaurus. It's like when you try to connect to the 5D or 7D, nothing works. There is a pit of spikes there. So we shove a peasant (The Klugesaurus) onto the spikes, killing him (it fails silently), so we can walk across the peasant's dead body to safety.
It's ugly and terrible, but:
It works every time.
If you don't do it, it doesn't work.
I have asked Canon multiple times if they would release source code for EOS Utility, which connects to the 5D and 7D perfectly. They have solidly refused each time. My coworker jokes that they don't want to reveal that they, too, are using a Klugesaurus.
Anyways, I just wanted to give you a heads up to that nasty detail.
I also have created a Python module to interface with the camera:
http://github.com/superjoe30/pyedsdk
There are code samples here and discussions on different ways of acomplishing it.