How can I get all the physical drive paths (\\.\PhysicalDriveX) on a Windows computer, with C/C++?
The answers in this question suggest getting the logical drive letter, and then getting the physical drive corresponding to that mounted drive. The problem is, I want to get all
physical drives connected to the computer, including drives that are not mounted.
Other answers suggest incrementing a value from 0-15 and checking if a drive exists there (\\.\PhysicalDrive0, \\.\PhysicalDrive1, ...) or calling WMIC to list all the drives.[
As these seem like they would work, they seem like they are not the best approach to be taking. Is there not a simple function such as GetPhysicalDrives that simply returns a vector of std::string's containing the paths of all the physical drives?
You can use QueryDosDevice. Based on the description, you'd expect this to list things like C: and D:, but it will also lists things like PhysicalDrive0, PhysicalDrive1 and so on.
The major shortcoming is that it will also list a lot of other device names you probably don't care about, so (for example) on my machine, I get a list of almost 600 device names, of which only a fairly small percentage is related to what you care about.
Just in case you care, some (old) sample code:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
int main(int argc, char **argv) {
char physical[65536];
char logical[65536];
if ( argc > 1) {
for (int i=1; i<argc; i++) {
QueryDosDevice(argv[i],logical, sizeof(logical));
std::cout << argv[i] << " : \t" << logical << std::endl << std::endl;
}
return 0;
}
QueryDosDevice(NULL, physical, sizeof(physical));
std::cout << "devices: " << std::endl;
for (char *pos = physical; *pos; pos+=strlen(pos)+1) {
QueryDosDevice(pos, logical, sizeof(logical));
std::cout << pos << " : \t" << logical << std::endl << std::endl;
}
return 0;
}
However, if I run this like `devlist | grep "^Physical", it lists the physical drives.
Yes, you can just type NET USE. Here is an example output...
NET USE
New connections will be remembered.
Status Local Remote Network
-------------------------------------------------------------------------------
H: \\romaxtechnology.com\HomeDrive\Users\Henry.Tanner
Microsoft Windows Network
OK N: \\ukfs01.romaxtechnology.com\romaxfs
Microsoft Windows Network
OK X: \\ukfs03.romaxtechnology.com\exchange
Microsoft Windows Network
OK Z: \\ukfs07\Engineering Microsoft Windows Network
\\romaxtechnology.com\HomeDrive
Microsoft Windows Network
OK \\ukfs07\IPC$ Microsoft Windows Network
The command completed successfully.
Related
Trying to get per-partition available disk space, I found many solutions online, all of them unfortunately don't work.
The question is: How to programmatically get available (free) space for a given partition?
What I tried:
#include <filesystem>
int main()
{
std::filesystem::path diskPath("/dev/disk0s1");
size_t space = std::filesystem::space(diskPath).available;
std::cout << "Free space for disk01: " << space << std::endl;
}
Unfortunately, I get the following compilation error:
'path' is unavailable: introduced in macOS 10.15
'path' has been explicitly marked unavailable here
I know there is a similar library in boost, but I would like to avoid boost if possible.
(Targeting 10.12 +)
#include <sys/statvfs.h>
int main()
{
struct statvfs buf;
if (!statvfs("/dev/disk0s1", &buf))
{
size_t space = buf.f_bfree*buf.f_bsize;
std::cout << "Free space for disk01: " << space << std::endl;
}
else
{
std::cerr << "Error here" << std::endl;
}
}
Unfortunately, this retrieve 0for all partitions. Note: some values like f_bsizeare filled correctly, but f_bfreeis always 0.
From this std::filesyste::space reference:
Determines the information about the filesystem on which the pathname p is located
[Emphasis mine]
That means the path you provide must be to a file or directory on the filesystem itself, not the path to the device file.
For example if /dev/disk0s1 is mounted as /home then you could use that mount path itself (i.e. std::filesystem::space("/home")).
Note that statvfs works exactly the same.
I am reading 2.2 million points from a PCD file, and loadPCDFile is using ca 13 sec both in Release as well as Debug mode. Given that visualization programs like CloudCompare can read the file in what seems like milliseconds, I expect that I am doing something harder than it needs to be.
What am I doing wrong?
The top of my PCD file:
# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS rgb x y z _
SIZE 4 4 4 4 1
TYPE F F F F U
COUNT 1 1 1 1 4
WIDTH 2206753
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 2206753
DATA binary
¥•ÃöèÝÃájfD ®§”ÃÍÌÝÃá:fD H”ø¾ÝÃH!fD .....
From my code, reading the file:
#include <iostream>
#include <vector>
#include <pcl/common/common.h>
#include <pcl/common/common_headers.h>
#include <pcl/common/angles.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/parse.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/features/normal_3d.h>
#include <boost/thread/thread.hpp>
int main() {
(...)
pcl::PointCloud<pcl::PointXYZRGB>::Ptr largeCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
largeCloud->points.resize(3000000); //Tried to force resizing only once. Did not help much.
if (pcl::io::loadPCDFile<pcl::PointXYZRGB>("MY_POINTS.pcd", *largeCloud) == -1) {
PCL_ERROR("Couldn't read file MY_POINTS.pcd\n");
return(-1);
}
(...)
return 0;
}
(Using PCL 1.8 and Visual Studio 2015)
Summary of below...
PCL is slightly slower at loading cloud compare formatted PCD files. Looking at the headers, CC seems to add an extra variable to each point "_" that PCL doesn't like and has to format out. But this is only a difference of 30%-40% load time.
Based on the result that with the same size point cloud (3M), my computer took 13 seconds to load it from cloud compare when the program was compiled in Debug mode and only 0.25s to load the same cloud in Release mode. I think that you are running in debug mode. Depending on how you compiled/installed PCL, you may need to rebuild PCL to generate the appropriate Release build. My guess is that whatever you think you are doing to change from Debug to Release is not in fact engaging the PCL release library.
In PCL, across almost all functions, moving from Debug to Release will often give you one to two orders of magnitude faster processing (due to PCL's heavy usage of large array objects that have to be managed differently in Debug mode for visibility)
Testing PCL with cloud compare files
Here is the code that I ran to produce the following outputs:
std::cout << "Press enter to load cloud compare sample" << std::endl;
std::cin.get();
TimeStamp stopWatch = TimeStamp();
pcl::PointCloud<pcl::PointXYZRGB>::Ptr tempCloud2(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::io::loadPCDFile("C:/SO/testTorusColor.pcd", *tempCloud2);
stopWatch.fullStamp(true);
std::cout <<"Points loaded: "<< tempCloud2->points.size() << std::endl;
std::cout << "Sample point: " << tempCloud2->points.at(0) << std::endl;
std::cout << std::endl;
std::cout << "Press enter to save cloud in pcl format " << std::endl;
std::cin.get();
pcl::io::savePCDFileBinary("C:/SO/testTorusColorPCLFormatted.pcd", *tempCloud2);
std::cout << "Press enter to load formatted cloud" << std::endl;
std::cin.get();
stopWatch = TimeStamp();
pcl::PointCloud<pcl::PointXYZRGB>::Ptr tempCloud3(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::io::loadPCDFile("C:/SO/testTorusColorPCLFormatted.pcd", *tempCloud3);
stopWatch.fullStamp(true);
std::cout << "Points loaded: " << tempCloud3->points.size() << std::endl;
std::cout << "Sample point: " << tempCloud3->points.at(0) << std::endl;
std::cout << std::endl;
std::cin.get();
Cloud compare generated colored cloud (3M points with color):
Running in Debug, reproduced your approximate load time with a 3M pt cloud:
Running in Release:
I was running into exactly this situation.
It simply comes down to file storage style. Your file (taking that long to load) is almost certainly an ASCII style point cloud file. If you want to be able to load it much faster (x100) then convert it to binary format. For reference, I load a 1M pt cloud in about a quarter second (but that is system dependent)
pcl::PointCloud<pcl::PointXYZ>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZ>);
The load call is the same:
pcl::io::loadPCDFile(fp, *tempCloud);
but in order to save as binary use this:
pcl::io::savePCDFileBinary(fp, *tempCloud);
Just in case it helps, here is a snippet of the code I use to load and save clouds (I structure them a bit, but it is likely based on an example, so I don't know how important that is but you may want to play with it if you switch to binary and are still seeing long load times).
//save pt cloud
std::string filePath = getUserInput("Enter file name here");
int fileType = stoi(getUserInput("0: binary, 1:ascii"));
if (filePath.size() == 0)
printf("failed file save!\n");
else
{
pcl::PointCloud<pcl::PointXYZ> tempCloud;
copyPointCloud(*currentWorkingCloud, tempCloud);
tempCloud.width = currentWorkingCloud->points.size();
tempCloud.height = 1;
tempCloud.is_dense = false;
filePath = "../PointCloudFiles/" + filePath;
std::cout << "Cloud saved to:_" << filePath << std::endl;
if (fileType == 0){pcl::io::savePCDFileBinary(filePath, tempCloud);}
else
{pcl::io::savePCDFileASCII(filePath, tempCloud);}
}
//load pt cloud
std::string filePath = getUserInput("Enter file name here");
if (filePath.size() == 0)
printf("failed user input!\n");
else
{
filePath = "../PointCloudFiles/" + filePath;
pcl::PointCloud<pcl::PointXYZ>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile(filePath, *tempCloud) == -1) //* load the file
{
printf("failed file load!\n");
}
else
{
copyPointCloud(*tempCloud, *currentWorkingCloud); std::cout << "Cloud loaded from:_" << filePath << std::endl;
}
}
List item
This looks correct, when comparing with a pcl example. I think the main work of loadPCDFile is done in the function pcl::PCDReader::read, which is located in the file pcd_io.cpp. When checking the code for binary data, as it is in your case, there are 3 nested for loops which check if the numerical data of each field is valid. The exact code comment is
// Once copied, we need to go over each field and check if it has NaN/Inf values and assign cloud
That could be time consuming. However, I am speculating.
I've been using Vim a lot lately, and I was wondering how the program manages to change the characters at certain positions in the terminal. For example, when using :rc, it replaces the character under the cursor with c.
I have also seen similar things done with Homebrew, which prints a progress bar to the screen and updates it when necessary.
How is this done in C/C++?
There is no standard way of doing this in C++.
It is done with OS dependent lbiraries, such as curses and similar libraries (ncurses) in the Unix/Linux world. Some of these libraries have been ported on across platforms (example: PDCurses)
For very simple things such as a progress bar or a counter, and as long as you remain on a single line there is the trick of using "\r" (carriage return) in the output, to place the cursor back at the begin of the current line. Example:
for (int i = 0; i < 100; i++) {
cout << "\rProgress: " << setw(3) << i;
this_thread::sleep_for(chrono::milliseconds(100));
}
Certainly, using ncurses or similar library is a good answer. An alternative may be to use ANSI Escape Codes to control the cursor in some terminal emulators (but not Windows command shell). For example, this code prints a line in multiple colors and then moves the cursor to 2,2 (coordinates are 1-based with 1,1 being the upper left corner) and prints the word "red" in the color red.
#include <iostream>
#include <string>
const std::string CSI{"\x1b["};
const std::string BLUE{CSI + "34m"};
const std::string RED{CSI + "31m"};
const std::string RESET{CSI + "0m"};
std::ostream &curpos(int row, int col)
{
return std::cout << CSI << row << ';' << col << 'H';
}
int main()
{
std::cout << "This is " << BLUE << "blue" << RESET << " and white.\n";
curpos(2,2);
std::cout << RED << "red" << RESET << '\n';
}
As mentioned that's not a matter of any C/C++ standard operations provided with stdout or cout (besides writing the necessary control characters to the screen).
Controlling the screen cursor of an ASCII terminal totally depends on implementation of the particular terminal program used, and besides a very narrow set of control characters, there's no standard established.
There are libraries like ncurses for a broader variety of linux terminal implementations, or PDcurses for a windows CMD shell.
I'm not sure to understand you completely but with creating an array of 100 elements of type char you can modify any position of the array and loop it with a std:cout to mostrate it on the console.
Perhaps could be better define the array of 50 chars to resuce the size of the printed result.
For example, if you have to print a progessbar in the 1% process, you should print:
Char progressbar[100] = {'X','','','','','','','','',........}
I'm using Microsoft Visual C++ Express, and I'm wondering what's wrong with the following application, I can't get an output, it gives me an error. Since I'm not English, the error is in a different language, but it basically says something along the lines of 'The system can't find the given/stated path'.
I have literally checked it a dozen times but I can't seem to find what I'm doing wrong. Here's the code:
#include <iostream>
using namespace std;
int DemoConsoleOutput ()
{
cout << "This is a simple string literal" << endl;
cout << "Writing number five:" << 5 << endl;
cout << "Performing division 10/5 = " << 10 / 5 << endl;
cout << "Pi when approximated is 22 / 7 = " << 22 / 7 << endl;
cout << "Pi more accurately is 22 / 7 = " << 22.0 / 7 << endl;
return 0;
}
int main()
{
return DemoConsoleOutput ();
}
Can anyone help me find what's wrong with this?
Addendum: I also keep getting a weird error on my computer every couple minutes. It says: 'a program can't display a message on the desktop' and it gives me the options to show the message, or to give me another reminder in a few minutes. When I click 'show message' my screen goes black for a second and it then gives an error 'The application data folder for Microsoft visual c++ 2010 express could not be created'.
I don't know if it's important, but my OS is windows vista.
From the situation it seems that the application has insufficient rights to create a working folder and write an file in that folder. Possible causes can be that your anti virus is not letting VS do so or the folder has no write rights. Please go through this question.
The Problem
I'm developing an 32 bit unmanaged application in C++ on Windows using Visual Studio 2010. Forgive my lack of Windows knowledge as I usually develop on *nix.
Initially, in my program my calls to std::cout's stream insertion operator work fine. For example, the following statement outputs as expected:
std::cout << "hello" << std::endl;
However, the following code does not work:
std::cout << "\thello" << std::endl;
...call to DLL from Japanese company who won't respond to support requests...
std::cout << "\thello" << std::endl;
The above code prints:
hello
(inverted diamond symbol)hello(eighth note music symbol)(inverted o symbol)
Once I have called this DLL for the first time my output to std::cout is forever messed up. The symbols that are printed are not found in an ASCII table. The inverted o symbol is a single unicode char that looks like the letter 'o' but the black part of the o is white, and the white part is black(inverted colors). The music symbol is the unicode 8th note character.
Any ideas on why this is happening and how to fix it? It seems that this DLL is messing up how control characters (chars starting with \) are outputted.
What I have tried so far
I thought this might be a locale issue since the DLL is from a Japanese company. However, after the DLL call the locale is still "C" just as it was before the call. I use the following to query the locale:
printf ("Locale is: %s\n", setlocale(LC_ALL,NULL) );
I also thought this might be some kind of bizarre memory corruption but it seems that the \r\n gets replaced by (music symbol)(inverted o) whereas \t gets replaced by an inverted diamond symbol. There seems to be a regular "replace A by B" pattern for all the control chars, which would not indicate memory corruption.
Lastly, I also tried this:
std::cout << "blah" << '\r' << '\n';
and I see the same garbage characters created by:
std::cout << "blah" << std::endl;
Thanks in advance for any help and insight.
See whether this fixes it:
#include <iostream>
#include <locale>
int main()
{
std::cout << "\thello" << std::endl;
// ...call to DLL from Japanese company who won't respond to support requests...
locale mylocale(""); // or "C" // Construct locale object with the user's default preferences
std::cout.imbue( mylocale ); // Imbue that locale
std::cout << "\thello" << std::endl;
return 0;
}
Consult the documentation for that library whether
the change of locale is by design
it can be configured otherwise
You could perhaps associate another stream with cout
std::ostream cout2;
cout2.rdbuf(std::cout.rdbuf());
And use it. I'm sure that won't be thread safe. Flushing might be 'awkward' - but it should work