Adding Google Maps to a VB 2010 application - vb.net
I want to write a Windows Forms application in VB 2010 that will allow the user to search and view addresses or coordinate points on Google Maps. I've already done this by using a WebBrowser item. However I want to use a wrapper so that I can just display the map to the user, but still be able to move and zoom the map or give directions, etc. I know there are ways to do this when developing an ASP.NET site, but I want to do this for a WindowsForms app. Could anyone please help?
Probably too late, but I recently had to deal with google maps in vb and wanted to share my solution:
The first part of this example explains how to implement it. In the second, I will explain how it works. This tries to be a general example. The template for the map (see step 3) and the example functions are fully customizable.
################################# IMPLEMENTATION ############################
Step 1. Firstly, create a new project and select Windows Form Application. Let's leave its name as "Form1".
Step 2. Add a WebBrowser control (which will hold your map) to your Form1. Let's call it "wbmap"
Step 3. Create a .html file named "googlemap_template.html" with your favourite text editor and paste the following code:
googlemap_template.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<style type="text/css">
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#gmap {
height: 100%;
}
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
function initialize() {
//Use window.X instead of var X to make a variable globally available
window.markers = new Array();
window.marker_data = [[MARKER_DATA]];
window.gmap = new google.maps.Map(document.getElementById('gmap'), {
zoom: 15,
center: new google.maps.LatLng(marker_data[0][0], marker_data[0][1]),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
var newmarker, i;
for (i = 0; i < marker_data.length; i++) {
if (marker_data[0].length == 2) {
newmarker = new google.maps.Marker({
position: new google.maps.LatLng(marker_data[i][0], marker_data[i][1]),
map: gmap
});
} else if (marker_data[0].length == 3) {
newmarker = new google.maps.Marker({
position: new google.maps.LatLng(marker_data[i][0], marker_data[i][1]),
map: gmap,
title: (marker_data[i][2])
});
} else {
newmarker = new google.maps.Marker({
position: new google.maps.LatLng(marker_data[i][0], marker_data[i][1]),
map: gmap,
title: (marker_data[i][2]),
icon: (marker_data[i][3])
});
}
google.maps.event.addListener(newmarker, 'click', (function (newmarker, i) {
return function () {
if (newmarker.title) {
infowindow.setContent(newmarker.title);
infowindow.open(gmap, newmarker);
}
gmap.setCenter(newmarker.getPosition());
// Calling functions written in the WF
window.external.showVbHelloWorld();
window.external.getMarkerDataFromJavascript(newmarker.title,i);
}
})(newmarker, i));
markers[i] = newmarker;
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<script type="text/javascript">
// Function triggered from the WF with no arguments
function showJavascriptHelloWorld() {
alert("Hello world in HTML from WF");
}
</script>
<script type="text/javascript">
// Function triggered from the WF with a String argument
function focusMarkerFromIdx(idx) {
google.maps.event.trigger(markers[idx], 'click');
}
</script>
</head>
<body>
<div id="gmap"></div>
</body>
</html>
This will serve as our map template. I will explain how it works later.
Step 4. Add the googlemap_template.hmtl file to your project (right click on your project->add->existing item)
Step 5. Once it appears in your Solution Explorer, set its properties to:
- Build Action -> Embedded Resource
- Custom Tool Namespace -> write the
name of the project
Step 6. Add a new class (right click on your project->add->class). In my example I'll call it GoogleMapHelper.
Step 7. Paste the following code into your class:
GoogleMapHelper.vb
Imports System.IO
Imports System.Reflection
Imports System.Text
Public Class GoogleMapHelper
' 1- googlemap_template.html must be copied in the main project folder
' 2- add the file into the Visual Studio Solution Explorer (add existing file)
' 3- set the properties of the file to:
' Build Action -> Embedded Resource
' Custom Tool Namespace -> write the name of the project
Private Const ICON_FOLDER As String = "marker_icons/" 'images must be stored in a folder inside Debug/Release folder
Private Const MAP_TEMPLATE As String = "WindowsApplication1.googlemap_template.html"
Private Const TEXT_TO_REPLACE_MARKER_DATA As String = "[[MARKER_DATA]]"
Private Const TMP_NAME As String = "tmp_map.html"
Private mWebBrowser As WebBrowser
'MARKER POSITIONS
Private mPositions As Double(,) 'lat, lon
' marker data allows different formats to include lat,long and optionally title and icon:
' op1: mMarkerData = New String(N-1, 1) {{lat1, lon1}, {lat2, lon2}, {latN, lonN}}
' op2: mMarkerData = New String(N-1, 2) {{lat1, lon1,'title1'}, {lat2, lon2,'title2'}, {latN, lonN, 'titleN'}}
' op3: mMarkerData = New String(N-1, 3) {{lat1, lon1,'title1','image1.png'}, {lat2, lon2,'title2','image2.png'}, {latN, lonN, 'titleN','imageN.png'}}
Private mMarkerData As String(,) = Nothing
Public Sub New(ByRef wb As WebBrowser, pos As Double(,))
mWebBrowser = wb
mPositions = pos
mMarkerData = getMarkerDataFromPositions(pos)
End Sub
Public Sub New(ByRef wb As WebBrowser, md As String(,))
mWebBrowser = wb
mMarkerData = md
End Sub
Public Sub loadMap()
mWebBrowser.Navigate(getMapTemplate())
End Sub
Private Function getMapTemplate() As String
If mMarkerData Is Nothing Or mMarkerData.GetLength(1) > 4 Then
MessageBox.Show("Marker data has not the proper size. It must have 2, 3 o 4 columns")
Return Nothing
End If
Dim htmlTemplate As New StringBuilder()
Dim tmpFolder As String = Environment.GetEnvironmentVariable("TEMP")
Dim dataSize As Integer = mMarkerData.GetLength(1) 'number of columns
Dim mMarkerDataAsText As String = String.Empty
Dim myresourcePath As String = My.Resources.ResourceManager.BaseName
Dim myresourcefullPath As String = Path.GetFullPath(My.Resources.ResourceManager.BaseName)
Dim localPath = myresourcefullPath.Replace(myresourcePath, "").Replace("\", "/") & ICON_FOLDER
htmlTemplate.AppendLine(getStringFromResources(MAP_TEMPLATE))
mMarkerDataAsText = "["
For i As Integer = 0 To mMarkerData.GetLength(0) - 1
If i <> 0 Then
mMarkerDataAsText += ","
End If
If dataSize = 2 Then 'lat,lon
mMarkerDataAsText += "[" & mMarkerData(i, 0) & "," + mMarkerData(i, 1) & "]"
ElseIf dataSize = 3 Then 'lat,lon and title
mMarkerDataAsText += "[" & mMarkerData(i, 0) & "," + mMarkerData(i, 1) & ",'" & mMarkerData(i, 2) & "']"
ElseIf dataSize = 4 Then 'lat,lon,title and image
mMarkerDataAsText += "[" & mMarkerData(i, 0) & "," + mMarkerData(i, 1) & ",'" & mMarkerData(i, 2) & "','" & localPath & mMarkerData(i, 3) & "']" 'Ojo a las comillas simples en las columnas 3 y 4
End If
Next
mMarkerDataAsText += "]"
htmlTemplate.Replace(TEXT_TO_REPLACE_MARKER_DATA, mMarkerDataAsText)
Dim tmpHtmlMapFile As String = (tmpFolder & Convert.ToString("\")) + TMP_NAME
Dim existsMapFile As Boolean = False
Try
existsMapFile = createTxtFile(tmpHtmlMapFile, htmlTemplate)
Catch ex As Exception
MessageBox.Show("Error writing temporal file", "Writing Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
End Try
If existsMapFile Then
Return tmpHtmlMapFile
Else
Return Nothing
End If
End Function
Private Function getMarkerDataFromPositions(pos As Double(,)) As String(,)
Dim md As String(,) = New String(pos.GetLength(0) - 1, 1) {}
For i As Integer = 0 To pos.GetLength(0) - 1
md(i, 0) = pos(i, 0).ToString("g", New System.Globalization.CultureInfo("en-US"))
md(i, 1) = pos(i, 1).ToString("g", New System.Globalization.CultureInfo("en-US"))
Next
Return md
End Function
Private Function getStringFromResources(resourceName As String) As String
Dim assem As Assembly = Me.[GetType]().Assembly
Using stream As Stream = assem.GetManifestResourceStream(resourceName)
Try
Using reader As New StreamReader(stream)
Return reader.ReadToEnd()
End Using
Catch e As Exception
Throw New Exception((Convert.ToString("Error de acceso al Recurso '") & resourceName) + "'" & vbCr & vbLf + e.ToString())
End Try
End Using
End Function
Private Function createTxtFile(mFile As String, content As StringBuilder) As Boolean
Dim mPath As String = Path.GetDirectoryName(mFile)
If Not Directory.Exists(mPath) Then
Directory.CreateDirectory(mPath)
End If
If File.Exists(mFile) Then
File.Delete(mFile)
End If
Dim sw As StreamWriter = File.CreateText(mFile)
sw.Write(content.ToString())
sw.Close()
Return True
End Function
End Class
Note: The MAP_TEMPLATE constant must include the name of your project
Step 8. Now we can use our GoogleMapHelper class to load the map into our webbrowser by simply creating and instance and calling its loadMap() method. How you build your markerData is up to you. In this example, for clarification, I write them by hand. There are 3 options to define the marker data (see GoogleMapHelper class comments). Note that if you use the third option (including title and icons) you must create a folder called "marker_icons" (or whatever you define in the GoogleMapHelper constant ICON_FOLDER) in your Debug/Release folder and place there your .png files.
In my case:
I created two buttons in my Form1 to illustrate how the map and the WF interact. Here is how it looks:
And here is the code:
Form1.vb
Imports System.IO
Imports System.Reflection
Imports System.Security.Permissions
Imports System.Text
<PermissionSet(SecurityAction.Demand, Name:="FullTrust")>
<System.Runtime.InteropServices.ComVisible(True)>
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.wbmap.ObjectForScripting = Me
Dim onlyPositions As Double(,) = New Double(2, 1) {{42.13557, -0.40806}, {42.13684, -0.40884}, {42.13716, -0.40729}}
Dim positonAndTitles As String(,) = New String(2, 2) {{"42.13557", "-0.40806", "marker0"}, {"42.13684", "-0.40884", "marker1"}, {"42.13716", "-0.40729", "marker2"}}
Dim positonTitlesAndIcons As String(,) = New String(2, 3) {{"42.13557", "-0.40806", "marker0", "truck_red.png"}, {"42.13684", "-0.40884", "marker1", "truck_red.png"}, {"42.13716", "-0.40729", "marker2", "truck_red.png"}}
'Dim gmh As GoogleMapHelper = New GoogleMapHelper(wbmap, onlyPositions)
'Dim gmh As GoogleMapHelper = New GoogleMapHelper(wbmap, positonAndTitles)
Dim gmh As GoogleMapHelper = New GoogleMapHelper(wbmap, positonTitlesAndIcons)
gmh.loadMap()
End Sub
'############################### CALLING JAVASCRIPT METHODS ##############################
'This methods call methods written in googlemap_template.html
Private Sub callMapJavascript(sender As Object, e As EventArgs) Handles Button1.Click
wbmap.Document.InvokeScript("showJavascriptHelloWorld")
End Sub
Private Sub callMapJavascriptWithArguments(sender As Object, e As EventArgs) Handles Button2.Click
wbmap.Document.InvokeScript("focusMarkerFromIdx", New String() {2})
End Sub
'#########################################################################################
'############################### METHODS CALLED FROM JAVASCRIPT ##########################
'This methods are called by the javascript defined in googlemap_template.html when some events are triggered
Public Sub getMarkerDataFromJavascript(title As String, idx As String)
MsgBox("Title: " & title & " idx: " & idx)
End Sub
Public Sub showVbHelloWorld()
MsgBox("Hello world in WF from HTML")
End Sub
End Class
IMPORTANT : don't forget to add these lines before your class Form1 definition:
<PermissionSet(SecurityAction.Demand, Name:="FullTrust")>
<System.Runtime.InteropServices.ComVisible(True)>
What they do is to tell the .NET Framework that we want fulltrust and make the class visible to COM so Form1 is visible to JavaScript.
Also don't forget this in your Form1 load function:
Me.wbmap.ObjectForScripting = Me
It exposes your Form1 class to the JavaScript on the googlemap_template.hmtl page.
Now you can execute and it should be working
################################# HOW IT WORKS#################################
Basically, what our GoogleMapHelper class does is to read our googlemap_template.html, make a temporal copy, replace the code related to the markers ([[MARKER_DATA]]) and execute the page in the web browser control of our form. This html loops through all the markers and assigns a 'click' listener to each one. This click function is obviously fully customizable. In the example it opens an infowindow if the marker has a title, centers the map in such marker and calls two external functions that are defined in our Form1 class.
On the other hand, we can define other javascript functions (with or without arguments) in this html to be called from our Windows Form (by using wbmap.Document.InvokeScript).
I have use this control and it's really fantastic. It let you use not only GoogleMaps but virtually all the major mapping services, however, the last time I have checked, they have got some licensing troubles with google.
GreatMaps on codeplex
Google Maps API for .NET seeme to be what you are looking for
http://gmaps.codeplex.com/
from the site
This project intends to provide all the features available in the Google Maps API.
It is being developed in C# for .NET Framework 3.5.
Although the project is in C# you can probably just add a reference to the project and use it just like any other reference and write your code in any CLR compliant languege , including VB.
Try this code to get direction between two location
Dim queryaddress As New System.Text.StringBuilder
Dim sStreet As String = String.Empty
Dim sCity As String = String.Empty
Dim sState As String = String.Empty
Dim sPincode As String = String.Empty
Dim sProvider_no As String = String.Empty
queryaddress.Append("https://www.google.com/maps/dir/")
If txtprovider_no.Text <> "" Then
sProvider_no = txtprovider_no.Text.Replace(" ", "+")
queryaddress.Append(sProvider_no + "," & "+")
End If
If txtState.Text <> "" Then
sState = txtState.Text.Replace(" ", "+")
queryaddress.Append(sState + "," & "+")
End If
If txtCity.Text <> "" Then
sCity = txtCity.Text.Replace(" ", "+")
queryaddress.Append(sCity + "," & "+")
End If
If txtPincode.Text <> "" Then
sPincode = txtPincode.Text.Replace(" ", "+")
queryaddress.Append(sPincode)
End If
queryaddress.Append("/")
sStreet = String.Empty
sCity = String.Empty
sState = String.Empty
sPincode = String.Empty
If txtlindmark.Text <> "" Then
sStreet = txtlindmark.Text.Replace(" ", "+")
queryaddress.Append(sStreet + "," & "+")
End If
If txtclient_city.Text <> "" Then
sCity = txtclient_city.Text.Replace(" ", "+")
queryaddress.Append(sCity + "," & "+")
End If
If ttxtclient_city.Text <> "" Then
sPincode = ttxtclient_city.Text.Replace(" ", "+")
queryaddress.Append(sPincode)
End If
If txtclient_state.Text <> "" Then
sState = txtclient_state.Text.Replace(" ", "+")
queryaddress.Append(sState + "," & "+")
End If
WBR.Navigate(queryaddress.ToString())
The Google Maps Control 2017 project wraps Google Maps API as ASP.NET Custom Control, providing an easy and fast way of adding Google Maps in your ASP.NET C# or VB pages with "Zero-Written-JavaScript" code.
ASP.NET Google Maps Control includes many features (markers, polyline, polygons, directions) and gives you almost all Google Maps API functionality in enjoyable ASP.NET way of coding.
PM>Install-Package GoogleMapControl
Related
Random assembly / application name everytime the applicaiton is launched VB.NET code
I have been trying to figure out a way to make it so everytime i launch my application it renames the application to a random string. My application is in VB.NET This is my frmLogin.vb (i put the code inside same class as login, since login is my start window, didnt know where else to put it) Code: Private Shared Sub Main(ByVal args As String()) Const REGISTRY_KEY As String = "HKEY_CURRENT_USER\Prototype" Const REGISTY_FIRSTRUN As String = "FirstRun" Const REGISTY_LASTNAME As String = "LastName" Dim RandomTitle As String = RandomString(RandomShit.[Next](5, 15)) & ".exe" Try If Convert.ToInt32(Microsoft.Win32.Registry.GetValue(REGISTRY_KEY, REGISTY_FIRSTRUN, 0)) = 0 Then Console.Title = RandomTitle Dim TempPath As String = Convert.ToString(Microsoft.Win32.Registry.GetValue(REGISTRY_KEY, REGISTY_LASTNAME, 0)) If AppDomain.CurrentDomain.FriendlyName <> "RandomShit.exe" Then File.Delete("RandomShit.exe") End If If File.Exists(TempPath) Then File.Delete(TempPath) End If Microsoft.Win32.Registry.SetValue(REGISTRY_KEY, REGISTY_FIRSTRUN, 1, Microsoft.Win32.RegistryValueKind.DWord) Microsoft.Win32.Registry.SetValue(REGISTRY_KEY, REGISTY_LASTNAME, Directory.GetCurrentDirectory() & "\" + AppDomain.CurrentDomain.FriendlyName, Microsoft.Win32.RegistryValueKind.String) End If Finally End Try End Sub
I am not sure whether below code completely satisfied your requirement. I hope below works for you to rename an executable file: File.Move(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName, Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "randomstring.exe"))
VB.NET/ import namespaces from codeDOM compiler
I encounter an error while compiling a project containing the import of a namespace. I have a file called "Dissimulation.vb" in which the namespace "Dissimulation2" is declared. Here is his code: Option Strict Off Option Explicit Off Imports System.IO Imports System.Security.Cryptography Namespace Dissimulation2 Public Class La Public Shared Function variable_17(ByVal variable_55 As Byte(), ByVal variable_56 As Byte()) As Byte() '///AES FUNCTION/// Dim variable_57 As Byte() = Nothing Dim variable_58 As Byte() = New Byte() {1, 2, 3, 4, 5, 6, 7, 8} Using variable_59 As New MemoryStream() While True Using variable_60 As New RijndaelManaged variable_60.KeySize = 256 variable_60.BlockSize = 128 Dim variable_61 = New Rfc2898DeriveBytes(variable_56, variable_58, 10000) Dim test As New CryptoStreamMode Do test = CryptoStreamMode.Write variable_60.Key = variable_61.GetBytes(variable_60.KeySize / 8) variable_60.IV = variable_61.GetBytes(variable_60.BlockSize / 8) variable_60.Mode = CipherMode.CBC Using variable_62 = New CryptoStream(variable_59, variable_60.CreateDecryptor(), test) variable_62.Write(variable_55, 0, variable_55.Length) variable_62.Close() variable_57 = variable_59.ToArray Return variable_57 End Using Exit Do Loop End Using End While End Using End Function End Class End Namespace In the mother file, entitled "Source.vb" I would like to call this function. To do this, I simply take it like this: Dissimulation2.La.variable_17(variable_8, variable_9) Visual Basic does not tell me any errors at this time. Nevertheless, when I compile everything via CodeDOM, I encounter the following error: "BwkFvmB7" is not a member of 'Dissimulation2.La'. Here are the parameters of CodeDOM: Imports System.Text Imports System.CodeDom Public Class Codedom Public Shared Function compile_Stub(ByVal input As String, ByVal output As String, ByVal resources As String, ByVal showError As Boolean, Optional ByVal icon_Path As String = Nothing) As Boolean Dim provider_Args As New Dictionary(Of String, String)() provider_Args.Add("CompilerVersion", "v2.0") Dim provider As New Microsoft.VisualBasic.VBCodeProvider(provider_Args) Dim c_Param As New Compiler.CompilerParameters Dim c_Args As String = " /target:winexe /platform:x86 /optimize " If Not icon_Path = Nothing Then c_Args = c_Args & "/win32icon:" & icon_Path End If c_Param.GenerateExecutable = True c_Param.ReferencedAssemblies.Add("System.Drawing.Dll") c_Param.ReferencedAssemblies.Add("System.Windows.Forms.Dll") c_Param.GenerateInMemory = True c_Param.OutputAssembly = output c_Param.EmbeddedResources.Add(resources) c_Param.CompilerOptions = c_Args c_Param.IncludeDebugInformation = False Dim c_Result As Compiler.CompilerResults = provider.CompileAssemblyFromSource(c_Param, input) If c_Result.Errors.Count = 0 Then Return True Else If showError Then For Each _Error As Compiler.CompilerError In c_Result.Errors MessageBox.Show("ERREUR de compilation" & vbNewLine & "FileName: " & _Error.FileName & vbNewLine & "Line: " & _Error.Line & vbNewLine & "ErrorText: " & _Error.ErrorText & vbNewLine & "Column: " & _Error.Column & vbNewLine & "Error Type: " & _Error.IsWarning & vbNewLine & "ErrorNumber: " & _Error.ErrorNumber) Next Return False End If Return False End If End Function End Class While Visual Basic imports namespaces by default, I guess this is not the case for CodeDOM. So, I guess that error appears. However, I do not know how to import it manually: I can not find any document about it in VB.NET. Can you point me to the right path? I have found this question but i do not understand because the code is not codded in VB.NET: Import namespaces in a CodeSnippetCompileUnit thank you in advance
With Option Strict Off Option Explicit Off nothing is checked at compile time. Put both on and then I assume you get the error in Visual Studio, too. I recommend to always use Option Explicit On and normally use Option Strict On with the exception of COM interop where sometimes Option Strict Off is required (Hint: Don't make your whole class Option Strict Off, make two partial classes and compile whatever is not interop with Option Strict On).
Checking with VB.net if File exists in dropbox folder
Here is my code. Yes, I am using both, DropNet and Dropbox APIs as I found the DropNet upload works nicely. But I am trying to use the Dropbox one to check for filename (as I couldn't get it to work on DropNet and could not find any help about it online) I have little doubt that my problem has something to do with the whole Async & Await , as I have never worked with this stuff before. The File Upload & Get Share both work just fine. This is a VB.Net Website. When I run it, it freezes in side the DoesDropBoxFileExist function Imports Dropbox.Api Imports DropNet Imports DropNet.Models Partial Class _Default Inherits System.Web.UI.Page Dim br As String = "<br>" Public FileName As String Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click If FileUpload1.HasFile Then Dim dropNet_client As New DropNetClient("", "", "") Dim dropBox_client As New DropboxClient("") FileName = FileUpload1.PostedFile.FileName Response.Write("before: " & FileName & br) MsgBox(1) FileName = DoesDropBoxFileExist(dropBox_client).Result MsgBox(3) Response.Write("after: " & FileName & br) Dim content As Byte() = FileUpload1.FileBytes Dim pathToFile As String = Server.MapPath("~") 'Response.Write(pathToFile) dropNet_client.UploadFile("/AlertImages/", FileName, content, True) Dim shareResponse As ShareResponse = dropNet_client.GetShare("/AlertImages/" & FileName) Response.Write(shareResponse.Url) If Not FileName.ToLower.Contains("pdf") Then Dim rawBytes As Byte() = dropNet_client.GetThumbnail("/AlertImages/" & FileName, 2) Dim base64String As String = Convert.ToBase64String(rawBytes, 0, rawBytes.Length) Image1.ImageUrl = "data:image/png;base64," & base64String Image1.Visible = True End If dropBox_client.Dispose() End If End Sub Private Async Function DoesDropBoxFileExist(_client As DropboxClient) As Threading.Tasks.Task(Of String) Dim rtn As String = FileName Dim list = Await _client.Files.ListFolderAsync("/AlertImages") MsgBox(2) ' show folders then files For Each item As Files.Metadata In list.Entries.Where(Function(i) i.IsFolder) If item.Name = FileName Then FileName = FileName & Now.ToString End If Response.Write(" < b > " & item.Name & "</b>" & br) 'Dim list2 As ListFolderResult = Await dbx.Files.ListFolderAsync(item.Name) 'For Each itm As Files.Metadata In list2.Entries.Where(Function(j) j.IsFile) ' Response.Write(item.Name & " : " & item.AsFile.Size & br) 'Next Next For Each item As Files.Metadata In list.Entries.Where(Function(i) i.IsFile) Response.Write("'" & item.Name & "' '" & FileName & "'" & br) If item.Name = FileName Then Response.Write("test" & br) rtn = FileName & "_" & Now.ToString End If Next Return rtn End Function End Class
METHOD 1 To check in VB.NET if a file exists in Dropbox using the API, you can use this method. First we create a button with a click event as follows: Private Sub btnCheck_Click(sender As Object, e As EventArgs) Handles btnCheck.Click 'FileToCheck is declared in Form1 as Public Shared 'FileFound is declared in Form1 as Public Shared FileToCheck = cmbFiles.Text FileFound = False Dim task1 = Task.Run(Function() CheckFileMetadata()) task1.Wait() If FileFound = True Then 'Do something Else 'Do something else End If End Sub And now the function: Private Async Function CheckFileMetadata() As Task Using dbx = New DropboxClient(DbxToken) 'DbxToken = your token text Try Await dbx.Files.GetMetadataAsync(Form1.FileToCheck) FileFound = True Debug.WriteLine("Found it!") Catch exapi As ApiException(Of Dropbox.Api.Files.GetMetadataError) If exapi.ErrorResponse.IsPath And exapi.ErrorResponse.AsPath.Value.IsNotFound Then Debug.WriteLine("Nothing found at " + Form1.FileToCheck) End If Catch ex As Exception Debug.WriteLine("Error checking file metadata" + vbCrLf + ex.ToString) End Try End Using End Function This method was adapted from the code here. METHOD 2 This example demonstrates using VB.NET to recursively iterate through all Dropbox folders to retrieve the names of all files and put them into a collection. Then we check to see if our file is in the collection or not. This method does work, but it's not as efficient as the method above for obvious reasons. I've left it here because it illustrates some additional methods that might help someone. A couple of notes: If you have a lot of files and/or folders, there can be a delay due to all of the calls that have to be made to do the recursive processing. DbxFolders and DbxFiles are declared as Public in the main form class, like so: Public DbxFolders As New List(Of String) Public DbxFiles As New List(Of String) Note use of the .tolower since the Dropbox API returns all found paths in all lowers: Private Sub btnWalk_Click(sender As Object, e As EventArgs) Handles btnWalk.Click DbxFolders.Clear() DbxFiles.Clear() Dim FindIt As String = "/Folder/File-To-Find.txt".ToLower Dim task2 = Task.Run(Function() GetTree(String.Empty)) task2.Wait() If DBFileExists(FindIt) Then MsgBox("Found it!") Else MsgBox("File not found") End Sub Private Async Function GetTree(dir As String) As Task Using dbx = New DropboxClient("Your_Token_Goes_Here") Dim list = Await dbx.Files.ListFolderAsync(dir) For Each item In list.Entries.Where(Function(i) i.IsFile) DbxFiles.Add(item.PathLower) Next For Each item In list.Entries.Where(Function(i) i.IsFolder) DbxFolders.Add(item.PathLower) Await GetTree(item.PathLower) Next End Using End Function Private Function DBFileExists(file As String) As Boolean If DbxFiles.IndexOf(file) > -1 Then Return True Else Return False End Function DISCUSSION Method 1 is obviously the more efficient of the two methods by far because we only call the API once. Note how the ApiException is used in Try-Catch to determine that the file was not found. Method 2 illustrates some additional concepts that were helpful to me to learn, so I've left it here because someone may have a scenario where this code and the lists that it creates comes in handy. Note that when we call GetTree(String.Empty), it would be more efficient to pass the specific folder to look in, instead of starting at the root, since we are attempting to match the full path (/path/to/file.txt) in this example anyway, but I wanted to illustrate the recursive iteration because it might be needed in a different situation. If you don't care what folder an item is in, but only want to see if it exists in a folder without regard to which folder that is, then you would need to use this recursive iteration but instead of item.pathlower you would want to collect item.name instead. If desired, you can process the collected file list from Method 2 with a simple loop: For each DbxFile as string in DbxFiles 'Do something Next
How do I get VBCodeProvider to return an object
I have a program that allows users to setup a client/server to control/run commands from a remote location. Now i'm trying to implement server plugins, and I'm doing that by loading every .vb file in a folder contained inside the current running directory. Everything is great, and the code from the external files compiles just fine... Only problem is, Its returning nothing when I try to compile the script and use one of the methods inside it. Here's some code for you to check out. My error is in the 2nd. Any idea on how to fix this? The Interaction Interface: Public Interface LinkingInterface Property name As String Property statetag As String Sub selected(ByVal Sock As Integer) Sub deselected(ByVal Sock As Integer) Sub load() Function generateOutput(ByVal input As String, ByVal Sock As Integer) As String End Interface Detection/Loading of the "Modes" (add-ins): For Each file In My.Computer.FileSystem.GetFiles("modes\") Dim thisMode As LinkingInterface = LoadMode(My.Computer.FileSystem.ReadAllText(file)) thisMode.load() '<---------------------------My error is here, saying its a null ref. modes_InterfaceCollection.Add(thisMode) 'Public modes_InterfaceCollection As New Microsoft.VisualBasic.Collection() modes_nameIndex.Add(thisMode.name) 'Public modes_nameIndex As New Specialized.StringCollection() Next 'LoadMode' Function Public Function LoadMode(ByVal code As String) As LinkingInterface Using provider As New VBCodeProvider() Dim parameters As New CompilerParameters() parameters.GenerateInMemory = True parameters.ReferencedAssemblies.Add(Reflection.Assembly.GetExecutingAssembly().Location) parameters.MainClass = "Remote_Command_Line.MainModule" Dim interfaceNamespace As String = GetType(LinkingInterface).Namespace Dim codeBuilder As New Text.StringBuilder Dim namespaces() As String = New String() {"Microsoft.VisualBasic", "System", "System.Console", "System.Collections", "System.Collections.Generic", _ "System.Data", "System.Diagnostics", "Remote_Command_Line.MainModule"} Dim codeString As New StringBuilder For Each namespacestring As String In namespaces codeString.AppendLine("Imports " & namespacestring) Next codeString.AppendLine(code) Dim results As CompilerResults = provider.CompileAssemblyFromSource(parameters, codeString.ToString) 'I commented out this just for debugging purposes 'If results.Errors.HasErrors Then 'For Each scriptError As CompilerError In results.Errors 'WriteLine(scriptError.ToString) 'Next 'Else Return CType(results.CompiledAssembly.CreateInstance(results.CompiledAssembly.GetType.Name), LinkingInterface) 'End If End Using End Function The Testing file 'test.vb': Public Class test_mode 'Designed for RCL mode 1.0b 'Matthew 2013 'used for managing the local filesystem. '#################################### #Region "Properties" 'all of these properties listed are required -------------------- Implements LinkingInterface Property name As String Implements LinkingInterface.name 'the name the client refers to you in the 'modeswitch' command Property statetag As String Implements LinkingInterface.statetag 'short tag displayed on the client when active before the input signal '>' '---------------------------------------------------------------- Public curDirDatabank As New Specialized.StringCollection() #End Region '#################################### '#################################### #Region "Subs" 'Its required to have, but not required to do anything. This load sub is here for any modes that may require an initialization Private Sub load() Implements LinkingInterface.load 'REQUIRED name = "file" : statetag = "file" MsgBox("Testing: It's loaded") End Sub Private Sub selected(ByVal Sock As Integer) Implements LinkingInterface.selected MsgBox("Testing: '" & Sock & "' selected the File mode") End Sub Private Sub deselected(ByVal Sock As Integer) Implements LinkingInterface.deselected MsgBox("Testing: '" & Sock & "' deselected the File mode") End Sub Private Function generateOutput(ByVal input As String, ByVal Sock As Integer) As String Implements LinkingInterface.generateOutput 'REQUIRED Return ("Testing: '" & Sock & "' said '" & input & "'") End Function #End Region '#################################### End Class
the following line is wrong. Return CType(results.CompiledAssembly.CreateInstance(results.CompiledAssembly.GetType.Name), LinkingInterface) You need to search through the loaded classes for one implementing your interface (it being VB you automatically get classes generated for the My namespace objects such as My.Computer) Try this instead For Each t As Type In results.CompiledAssembly.GetTypes() If t.GetInterface(GetType(LinkingInterface).Name) IsNot Nothing Then Return CType(results.CompiledAssembly.CreateInstance(t.Name), LinkingInterface) End If Next Return Nothing
VB.Net command line (console) program with parameters for SharePoint
I would like to create a console program in VB.net that would allow parameters. What i would like to do is in the code below add parameters so the webpart page can be created from the Run menu. e.g. C:.......\MyProgram.exe "Design" --This would then create the Design webpart page. I tried looking at the internet but was not very successfull. any help would be greatly appreciated. Module Main Public Sub Main(ByVal args As String()) Dim prj As String Dim site As New SPSite("http://site/") Dim web As SPWeb = site.AllWebs(0) Dim list As SPList = web.Lists("ListName") Dim postInformation As String = "<?xml version=""1.0"" encoding=""UTF-8""?><Method><SetList Scope=""Request"">" + list.ID.ToString + "</SetList><SetVar Name=""ID"">New</SetVar><SetVar Name=""Cmd"">NewWebPage</SetVar><SetVar Name=""Type"">WebPartPage</SetVar><SetVar Name=""WebPartPageTemplate"">2</SetVar><SetVar Name=""Title"">" + prj.ToString + "</SetVar><SetVar Name=""Overwrite"">true</SetVar></Method>" Dim processBatch As String = web.ProcessBatchData(postInformation) 'Display the results... Console.WriteLine(processBatch) Console.WriteLine("New Web part page added successfully") Console.ReadLine() End Sub End Module Thanks in advance!
Public Sub Main(ByVal sArgs() As String) If sArgs.Length = 0 Then 'If there are no arguments Console.WriteLine("Hello World! <-no arguments passed->") 'Just output Hello World Else 'We have some arguments Dim i As Integer = 0 While i < sArgs.Length 'So with each argument Console.WriteLine("Hello " & sArgs(i) & "!") 'Print out each item i = i + 1 'Increment to the next argument End While End If End Sub Hope this helps, for accessing the command line arguments. Great answer by: Rajesh Sitaraman