|
The hardest part would be the recursive funtion to scan the folders. There's an example on that over here[^], and also on the Knowledge Base[^].
The rest is up to you
I are Troll
|
|
|
|
|
Easily done by shelling to a DOS command that creates a text file, then parsing this if necessary:
The following DOS command will create a file called Output.txt with a list of all files (not including system or hidden) on drive c: - the /s recurses subdirectories, and the /b restricts the output to filename only.
DIR C: /s /b >Output.txt
====================================
Transvestites - Roberts in Disguise!
====================================
|
|
|
|
|
How to Redirect a LinkLabel from one window form to another window form in VB 2005?
|
|
|
|
|
form.show
or
form.ShowDialog
SOFTDEV
If you have knowledge, let others light their candles at it. [ Let's work to help developers, not make them feel stupid ]
|
|
|
|
|
Hi,everyone.I am hoping that the text that I input in the textbox can be captured in the
excel each sheet ,column 3, rows 2-20 for example.
Code like under,I think there are many errors in it,please tell me how to write it,please.
Thanks!
Imports Office = Microsoft.Office.Core
Imports Microsoft.Office.Interop.Excel
Private Sub OperateExcel()
Dim Xls As Object
Dim Xlsbook As Excel.Workbook
Dim Xlssheet As Excel.Worksheet
Dim Xlsrange As Excel.Range
Xls = CreateObject("excel.application")
Xlsbook = Xls.Workbooks.open("D:\text.xls")
Xls.Visible = True
Xlssheet = Xlsbook.Worksheets("sheet1")
For Each Xlssheet In Xls.Xlsbook
Xlsrange = Xlssheet.Range("H3")
Xlsrange.Value = txtProduct.Text
Xlsrange = Xlssheet.Range("H4")
Xlsrange.Value = txtName.Text
Xlsrange = Xlssheet.Range("H5")
Xlsrange.Value = txtNum.Text
Next
Xlsbook.Close()
Xls.Quit()
releaseObject(Xls)
releaseObject(Xlsbook)
releaseObject(Xlssheet)
End Sub
modified on Friday, May 7, 2010 1:12 AM
|
|
|
|
|
Where to start...
I am not exactly sure what you are trying to achieve, and I take it you assembled this code from examples, or copied it as is.
So let's start from the beginning. If you suspect that this code has errors, the first thing you should do is put all the code inside the sub into a try catch clause:
Private Sub OperateExcel()
Try
'the rest of the code here'
Catch ex as Exception
MsgBox(ex.tostring)
End Try
End Sub
Then at least you'll find out if this code works at all. After that comes the important part, comparing what this code does to what you want it to do.
A simple way to start is to write comments into the code. One comment for each step, and then fill in the code bits doing each step.
My advice is free, and you may get what you paid for.
|
|
|
|
|
Hi,Johan,thanks for your suggestion.I apologize for the late reply...I used try catch clause in my code and then it told me an exception like this:
system.runtime.interop services.COMException(0x80020003):member not found.
it comes from:xlssheet = xlsworkbook.worksheet(1)
Could you give me suggestions to solve it?Thank you
modified on Saturday, May 8, 2010 9:35 PM
|
|
|
|
|
Hi sanyexian,
I changed your code a little bit so that it works. Still you might encounter many traps, since communication with Excel (i.e. COM / Office) can be very tricky sometimes. Also don't forget the small things, like making your assembly COM visible (project properties). You'll find tons of material about the issue here and in the web - and a lot is worth reading. Good luck
Sub OperateExcel()
' Compile with Option Strict Off to allow late binding.
Dim xlsApp As Object
Dim xlsBook As Object
Dim xlsSheet As Object
xlsApp = CreateObject("Excel.Application")
' Late bind an instance of an Excel workbook.
xlsBook = xlsApp.Workbooks.Add
' Late bind an instance of an Excel worksheet.
xlsSheet = xlsBook.Worksheets(1)
xlsSheet.Activate()
' Show the application.
xlsSheet.Application.Visible = True
For Each xlsSheet In xlsBook.worksheets
' put your text into the cells in a simpler way
xlsSheet.Range("H3").Value = "txtProduct"
xlsSheet.Range("H4").Value = "txtName"
xlsSheet.Range("H5").Value = "txtNum"
' A more useful way since you can iterate through rows/colums
' Here: Place some text in the second row of the sheet.
xlsSheet.Cells(2, 8) = "This is column H row 2"
Next
xlsBook.SaveAs("D:\text.xls")
xlsBook.Close()
xlsApp.Quit()
xlsSheet = Nothing
xlsBook = Nothing
xlsApp = Nothing
End Sub
|
|
|
|
|
How did that saying go again, about giving a man a fish...?
My advice is free, and you may get what you paid for.
|
|
|
|
|
You're surely right on one side. On the other side I've experienced so many other traps communicating with Office (and still do, as you know from my own thread ), that he will have to dig deeper for himself anyway. Probaly he even gets more motivated by having an easier start
|
|
|
|
|
Hi,Michael.I apologize for the late reply.Thanks for your suggestion.Now I could open a Excel file,but there is an error stoped me going on.
xlsSheet = xlsBook.Worksheets(1)
I watched "xlsSheet",it display that its value was "nothing" and VS told me " HRESULT:0x80020003 (DISP_E_MEMBERNOTFOUND))"
I don't know why it happened...the file had been opened ,but why it could not get its worksheet?
Plzzz help me ,thank you!
modified on Saturday, May 8, 2010 9:34 PM
|
|
|
|
|
Hi Sanyexian,
you can try xlsSheet = xlsBook.Worksheets.Add to add a new worksheet instead of referring the first available sheet with "1" (as suggested: play with IntelliSense!). The code is very basic anyway, you will need to catch exceptions (Try... Catch) and much more. You might also want to download some samples from the web and learn from them - as I wrote COM-Interaction can be tricky.
Good luck!
|
|
|
|
|
I have a little tool that I use in my job for running scripts on remote machines and gathering information. Currently I'm doing this through the process class and plink/SSH which works ok. My company is looking at doing away with the SSH server on the boxes which leaves me looking for another method. I know there is psexec which might work although by default most ports are blocked by the firewall, so not positive. Is there any way I can do it programatically without the need to involve an additional application? Any method I use I need to be able to capture the output as the majority of scripts are for gathering information without logging into the server. Any help would be appreciated.
|
|
|
|
|
A simple alternative that I use for this kind of thing, is ftp. Obviously this requires an ftp server that you can upload things to from anywhere.
Its pretty straightforward, but I don't think it works with sftp.
Private Sub FTP_PutFile(ByVal DestinationFileName As String, ByVal SourceFileName As String, ByVal usr As String, ByVal pwd As String)
Dim brwsr As New System.Net.WebClient
Dim creds As New System.Net.NetworkCredential(usr, pwd)
Try
With brwsr
.Credentials = creds
Console.WriteLine("Uploading file...")
.UploadFile(DestinationFileName, SourceFileName)
Console.WriteLine("Upload successful.")
.Dispose()
End With
Catch ex As Exception
EC(ex)
End Try
End Sub
Example use:
FTP_PutFile("ftp://server.address.or.ip/file.extension", "c:\temp\file.extension", "user", "password")
Just replace the .UploadFile bit with .DownloadFile(SourceFileName, DestinationFileName) when you want to download the file from the server.
My advice is free, and you may get what you paid for.
|
|
|
|
|
I don't have any problems with getting files there as I have a network share that is accessible from all machines. I need a way to actually run the file or process on the remote machine though and capture the output of that file/process.
|
|
|
|
|
Sorry about that, I misunderstood the question. I am afraid I can't help you with this.
My advice is free, and you may get what you paid for.
|
|
|
|
|
I know the name of Domain on NT platform "MY_Domain_name".
I know the username "OU458778".
Is possibile to know the complete name of username????
With vb6, please.
|
|
|
|
|
What do you mean by complete name? Like My_Domain_name\OU458778 or just the user's name like John Smith?
|
|
|
|
|
yes! just the user's name like John Smith
|
|
|
|
|
I don't have a copy of VB6 to test this with, but this VBScript code should translate pretty closely. You just need to do a WMI query against the Win32_UserAccount class. Name is the User ID and FullName should be the formatted name.
strUserID = InputBox("Please enter the User ID you wish to find")
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objAccountColl = objWMIService.ExecQuery("Select * from Win32_UserAccount where Name = '" & strUserID & "'")
For Each objAccount in ObjAccountColl
strValue = "AccountType: " & objAccount.AccountType & vbCrLf & _
"Caption: " & objAccount.Caption & vbCrLf & _
"Description: " & objAccount.Description & vbCrLf & _
"Disabled: " & objAccount.Disabled & vbCrLf & _
"Domain: " & objAccount.Domain & vbCrLf & _
"FullName: " & objAccount.FullName & vbCrLf & _
"InstallDate: " & objAccount.InstallDate & vbCrLf & _
"LocalAccount: " & objAccount.LocalAccount & vbCrLf & _
"Lockout: " & objAccount.Lockout & vbCrLf & _
"Name: " & objAccount.Name & vbCrLf & _
"PasswordChangeable: " & objAccount.PasswordChangeable & vbCrLf & _
"PasswordExpires: " & objAccount.PasswordExpires & vbCrLf & _
"PasswordRequired: " & objAccount.PasswordRequired & vbCrLf & _
"SID: " & objAccount.SID & vbCrLf & _
"SIDType: " & objAccount.SIDType & vbCrLf & _
"Status: " & objAccount.Status
MsgBox strValue
Exit For
Next
|
|
|
|
|
ok tks for reply...
But i dont see where i insert the name of domain?
|
|
|
|
|
Hey all!
that's really odd: I have a program that hashes files.
Until now I used 1 thread to do that.
Get all files in a folder into an array list (Dim aryFi As IO.FileInfo() = di.GetFiles("*.*"))
Then with a FOR NEXT loop I hash every file in the list and add the informations to a datatable.
Now I thought I could make this faster, using 2 threads.
So I figured it out, got it to work and it's slower than before??
I tested it:
Single thread took 33 sec to hash 1000 files.
2 threads took 49 sec to hash (another) 1000 files.
(and I made sure that there was no caching by OS)
how comes? using 2 threads I split the array in 2 parts, thread_1 from 0 to half, thread_2 from half+1 to array.count-1
I call both threads like this:
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
The joins are there because I store the info in 2 tables and after the threads are done I make 1 table out of them.
The only problem is, why does hashing take more time than single-threaded?
The program doesn't use much cpu ressources, 2-5% only (single thread version uses 3-6%), so there's plenty of free resources.
Can anyone explain or help?
edit:
The "best" thing is, the table later contains NOT the same information as singlethreaded table does ...
the hashed files count is the same using 1 or 2 threads (resulting datatable has the same amount of rows), but the hash info seems different ...
I compare the hashes of each file with stored hashes in a 2nd database.
For example: Using the hashtable of the single-thread version gets me 240 hits.
Using the hashtable made using 2 threads gets me 222-235 hits, that number varies each time I restart the procedure ...
That is odd and I can't see why this happens at all ...
Thanks in advance,
Nik
modified on Thursday, May 6, 2010 11:54 AM
|
|
|
|
|
This is not uncommon. Adding one or a few threads is fine when the operation is compute-bound and you have a multi-core, so a single thread would leave all but one cores unused. Adding threads however increases the load on all subsystems (disk, main memory, cache memory, buses, ...) and adds a small overhead too, as you now need more stacks, some synchronization, and of course some thread switching. So it is conceivable you just go from one bottleneck to another, and while doing so, the cache efficiency may go down (a phenomenon known as 'cache trashing').
I just performed a little Parallel.For experiment myself the other day, and, while I must admit it was very I/O bound, it ran 5 times slower on a dual-core than the straightforward single-thread implementation.
However switching from 1 to 2 threads, I would not expect calculating file hashes would actually slow down, well not on a normal system, with a typical disk (I am assuming your files are on a local disk, not a network disk, not a USB stick). So there always is the possibility you did something wrong, maybe you are forcing a synchronization somehow, I would need to see the code to tell for sure.
Some implementation questions would be:
are you reading the entire file to memory, or are you streaming the data?
are you using new buffers all the time, or reusing them?
|
|
|
|
|
Hello Luc,
thanks for replying
Now I have a little problem. I never learned VB.net, (somehow I even wonder how I was able to write a program like that, lol) I browsed the www and looked for the infos I need, experimented with code snippets and everything works like a charm, except the current problem where I want to make it a bit faster using 2 threads.
I updated the start post before I saw your reply.
My computer's a quadcore/iQ6600.
While the 2 threads are working (even if it's the single-thread methode) my hdd-LED doesn't flash much, I mean it's only flickering now and then, so I guess it doesn't put much load on the hdd.
hm I hope it's ok to paste the code here:
Private hashdups_m As Thread
Private hashdups_t1 As Thread
Private hashdups_t2 As Thread
Private Sub hash_folder()
Dim di As New IO.DirectoryInfo(src_cmp_fldr)
Dim aryFi As IO.FileInfo() = di.GetFiles("*.*")
If di.GetFiles("*.*").Length.ToString <> 0 Then
di_hashdups = New IO.DirectoryInfo(src_cmp_fldr)
aryFi_hashdups = di_hashdups.GetFiles("*.*")
hashdups_m = New Thread(AddressOf hashdups_main)
hashdups_m.Start()
End If
End Sub
Private Sub hashdups_main()
progb2val_a = 0
progb2val_b = 0
hashdups_t1 = New Thread(AddressOf hashdups_hash1)
hashdups_t2 = New Thread(AddressOf hashdups_hash2)
If aryFi_hashdups.Count = 1 Then
progb2val_b = 50
hashdups_t1.Start()
hashdups_t1.Join()
End If
If aryFi_hashdups.Count > 1 Then
hashdups_t1.Start()
hashdups_t2.Start()
hashdups_t1.Join()
hashdups_t2.Join()
End If
If hashdups_t1.IsAlive = False And hashdups_t2.IsAlive = False Then
ds_db_cmp_fldr.Tables.Add("db_cmp_fldr")
dt_db_cmp_fldr = ds_db_cmp_fldr.Tables("db_cmp_fldr")
Dim col_fs_dec As DataColumn = New DataColumn("filesize")
col_fs_dec.DataType = System.Type.GetType("System.Decimal")
dt_db_cmp_fldr.Columns.Add(col_fs_dec)
Dim col_sha1_string As DataColumn = New DataColumn("sha256hash")
col_sha1_string.DataType = System.Type.GetType("System.String")
dt_db_cmp_fldr.Columns.Add(col_sha1_string)
Dim col_fn_string As DataColumn = New DataColumn("filename")
col_fn_string.DataType = System.Type.GetType("System.String")
dt_db_cmp_fldr.Columns.Add(col_fn_string)
If ds_db_cmp_fldr.Tables.Contains("db_cmp_fldr_a") = True Then
For Each drSource_a As DataRow In dt_db_cmp_fldr_a.Rows
dt_db_cmp_fldr.ImportRow(drSource_a)
Next
ds_db_cmp_fldr.Tables.Remove("db_cmp_fldr_a")
End If
If ds_db_cmp_fldr.Tables.Contains("db_cmp_fldr_b") = True Then
For Each drSource_b As DataRow In dt_db_cmp_fldr_b.Rows
dt_db_cmp_fldr.ImportRow(drSource_b)
Next
ds_db_cmp_fldr.Tables.Remove("db_cmp_fldr_b")
End If
Me.Invoke(New upd_hashdups_m(AddressOf upd_hashdups_m_val), 1)
End If
End Sub
Private Sub hashdups_hash1()
ds_db_cmp_fldr.Tables.Add("db_cmp_fldr_a")
dt_db_cmp_fldr_a = ds_db_cmp_fldr.Tables("db_cmp_fldr_a")
Dim col_fs_dec_a As DataColumn = New DataColumn("filesize")
col_fs_dec_a.DataType = System.Type.GetType("System.Decimal")
dt_db_cmp_fldr_a.Columns.Add(col_fs_dec_a)
Dim col_sha1_string_a As DataColumn = New DataColumn("sha256hash")
col_sha1_string_a.DataType = System.Type.GetType("System.String")
dt_db_cmp_fldr_a.Columns.Add(col_sha1_string_a)
Dim col_fn_string_a As DataColumn = New DataColumn("filename")
col_fn_string_a.DataType = System.Type.GetType("System.String")
dt_db_cmp_fldr_a.Columns.Add(col_fn_string_a)
Dim myNewRow As DataRow
Dim aryficnt_a As Integer = Math.Ceiling(aryFi_hashdups.Count / 2)
For r1 = 0 To aryficnt_a - 1
result = Nothing
hashclass.HashFile(aryFi_hashdups(r1).FullName)
myNewRow = dt_db_cmp_fldr_a.NewRow()
myNewRow("filesize") = aryFi_hashdups(r1).Length
myNewRow("sha256hash") = result
myNewRow("filename") = aryFi_hashdups(r1).Name
dt_db_cmp_fldr_a.Rows.Add(myNewRow)
progb2val_a = (50 * (r1 + 1) / aryficnt_a)
Me.Invoke(New upd_progbar2_hash(AddressOf progbar2_val_hash), Convert.ToString(0))
Next
Me.Invoke(New upd_progbar2_hash(AddressOf progbar2_val_hash), Convert.ToString(0))
End Sub
Private Sub hashdups_hash2()
ds_db_cmp_fldr.Tables.Add("db_cmp_fldr_b")
dt_db_cmp_fldr_b = ds_db_cmp_fldr.Tables("db_cmp_fldr_b")
Dim col_fs_dec_b As DataColumn = New DataColumn("filesize")
col_fs_dec_b.DataType = System.Type.GetType("System.Decimal")
dt_db_cmp_fldr_b.Columns.Add(col_fs_dec_b)
Dim col_sha1_string_b As DataColumn = New DataColumn("sha256hash")
col_sha1_string_b.DataType = System.Type.GetType("System.String")
dt_db_cmp_fldr_b.Columns.Add(col_sha1_string_b)
Dim col_fn_string_b As DataColumn = New DataColumn("filename")
col_fn_string_b.DataType = System.Type.GetType("System.String")
dt_db_cmp_fldr_b.Columns.Add(col_fn_string_b)
Dim myNewRow As DataRow
Dim aryficnt_b As Integer = Math.Ceiling(aryFi_hashdups.Count / 2)
For r2 = aryficnt_b To aryFi_hashdups.Count - 1
result = Nothing
hashclass.HashFile(aryFi_hashdups(r2).FullName)
myNewRow = dt_db_cmp_fldr_b.NewRow()
myNewRow("filesize") = aryFi_hashdups(r2).Length
myNewRow("sha256hash") = result
myNewRow("filename") = aryFi_hashdups(r2).Name
dt_db_cmp_fldr_b.Rows.Add(myNewRow)
progb2val_b = (50 * (r2 - aryficnt_b + 1) / aryficnt_b)
Me.Invoke(New upd_progbar2_hash(AddressOf progbar2_val_hash), Convert.ToString(0))
Next
Me.Invoke(New upd_progbar2_hash(AddressOf progbar2_val_hash), Convert.ToString(0))
End Sub
the hashclass:
Public Class hashclass
Public Shared Function HashFile(ByVal File As String) As String
Dim FN As New FileStream(File, FileMode.Open, FileAccess.Read, FileShare.Read, 8192)
Dim HashValue(0) As Byte
Dim Tmp As String = ""
Dim SHA256 As New SHA256Managed
SHA256.ComputeHash(FN)
HashValue = SHA256.Hash
FN.Close()
For i As Integer = 0 To HashValue.Length - 1
Tmp = Hex(HashValue(i))
If Len(Tmp) = 1 Then Tmp = "0" & Tmp
result += Tmp
Next
Return result
End Function
End Class
Maybe there's an easier way than I found, but it works
The single thread version nearly looks the same, it skips making 2 tables and later reading both into a new table. Also the FOR NEXT loop is just from 0 to aryFi_hashdups.Count - 1
I just don't see why it varies like I wrote in the startpost.
If you need any other infos, please ask
Thanks,
Nik
|
|
|
|
|
Hi Nik,
I'm sorry to say but that code is rather horrible. I haven't studied it all, however here are first comments:
1.
there is way too much code; from your description, I would estimate the hashing should take no more than 20 lines of code.
2.
please check how often you call GetFiles(). You really need only one of those; calling it more than once wastes a lot of cycles and bytes, and does not guarantee all results will be identical, as your file system is a live object itself.
3.
you really should separate the functionality (calculate hash on a number of files) from other issues, such as the way you want to store things (DataTable).
4.
IIRC you did not mention progress bars before; they are the first suspect for the slowness. You did use Invoke (which you must), however this causes two thread switches (to the GUI thread and back), slowing down everything by a large factor.
This is how I would do this (initial approach):
1. create a little class "Result" holding filename, filesize, hashvalue
2. create a class "Job", holding a List of strings for filenames, a List of Results, and some code.
Necessary code would be:
2a. a Launch method that creates a thread which starts enumerating filenames (from its own input List), and produces results (in its own List of Results)
2b. a Join method that waits for termination, using the Thread.Join method.
3. in the main code:
3a. create N Job instances (assume N is 1 or 2) and keep them in a List of Job
3b. get a collection of all the files, and distribute them over the List of filenames in all the jobs
3c. launch the jobs
3d. wait on all jobs done
3e. go collect the results of all the jobs and post-process them
If you want progrss indication:
- give each Job a filesDone counter;
- add a System.Windows.Forms.Timer with Interval=100 that enumerates all jobs, totalizes their filesDone value, and sets that as the ProgressBar,Value (where ProgressBar.Maximum was set to the number of files returned by the initial GetFiles)
I know, all the above really says is: throw away what you have; start all over, and keep things as clean as possible.
Good luck!
PS: the above "first approach" is not optimal; there are a couple of ways to improve it, but it would be quite good if you tried it like that before going for gold.
|
|
|
|
|