I am using wxWidgets in Mac with C++ (obviously) and Xcode.
This line returns false, when it should be true.
` if(!wxFileExists(filePicker->GetPath())
{
wxMessageDialog(this, "error").ShowModal();
return;
} `
where filePicker is a wxFilePickerCtrl. It's value is :
filepath std::__1::string "/Users/swtsvn/Main/Proj1/Mac/binaries/osx/Debug/wxSampleApp.app"
The path has upper case, and no spaces. The File is located in that path, since I picked that file path using file picker wxWidget tool.
I searched for a reason wxFileExists might return false on Mac but not on Windows, but could not find one in Google.
If anyone knows the answer, kindly let me know.
According to the docs, wxFileExists():
Returns true if the file exists and is a plain file.
So, it returns false for directories. Mac app bundles, such as your wxSampleApp.app, are directories. It is the intentional behavior of the function that it return false in this case.
You could presumably use wxFileExists(path) || wxDirExists(path) instead, although that will be somewhat inefficient.
Related
I have a variable in Swift code that runs in iOS simulator and contains an existing fileURL. I want to have the file opened in macOS (not the iOS Simulator) when I hit a breakpoint.
I added an action "Shell Command" to the breakpoint to open the file. The file exists because if I copy-paste the file's path to Terminal, it opens in Preview.
However, the Xcode console says the contrary:
The file /"/Users/tomkraina/Library/Developer/CoreSimulator/Devices/FBA16E00-9450-40E8-9650-1489A67E344C/data/Containers/Data/Application/BB97DB72-FF2A-4087-BD42-2934C63D3323/tmp/7E2303B8-0629-475A-862A-2550351FB448/OutlineExport.pdf" does not exist.
First Question: How do I tell Xcode to open a file with provided fileURL in a variable on breakpoint?
Next thing I tried was to open the file using LLDB, but I cannot find out how to evaluate a command parameter in LLDB, because backticks is only for scalars:
(lldb) shell open `temporaryFile.fileURL.path`
The file /105553157711856 does not exist.
Second Question: How to I evaluate argument parameter to get a string in LLDB?
I don't have a good answer for the first question. It would be interesting to check whether the path that is in the Xcode error message is correct - maybe it's getting it from the value incorrectly. If you copy the path from the error message, go to Terminal and try to open it, does that work? Anyway, this sounds to me like a bug in Xcode. It got some kind of path out of your variable and tried to open it, which should have worked. If you want to follow up, it's probably best to file a bug report with the Apple Feedback.
For the second question, you have to know a little about how variables work in lldb. Some variables have obvious values, for instance, in C a pointer has the pointer value, an integer the integer value, etc. Other variables (any kind of Struct being the obvious example) are actually containers of other values and don't really have a "value" themselves.
lldb can show you what a swift string really is using the --raw option:
(lldb) v --raw str1
(Swift.String) str1 = {
_guts = {
_object = {
_countAndFlagsBits = {
_value = -3458764513820540912
}
_object = 0x8000000100003f50 (0x0000000100003f50) strings`symbol stub for: Swift.print(_: Any..., separator: Swift.String, terminator: Swift.String) -> () + 4
}
}
}
That's probably really interesting to people working on the Swift Standard Library and has the virtue of being the truth. But for most purposes, it's not a terribly useful representation.
lldb handles that problem by adding a notion of "Summary Formatters" that generate a string representation for objects based on their type. There's one for "Swift.string" that digs around in the object, finds where the actual string is, and returns that text. If you don't pass --raw and there's a summary formatter, then lldb will show you the summary:
(lldb) v str1
(String) str1 = "some string here"
That is also the value that you want to try and open.
The backtick syntax in lldb gets the value of the entity, not its summary, which is why that didn't work for a swift string. However, you can fetch and act on the summaries for local variables using lldb's Python interpreter and the SB API. So for instance:
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> var = lldb.frame.FindVariable("str1")
>>> var.GetSummary()
'"some string here"'
So then if that was a file path you wanted to open, you can use Python to do that, like:
>>> os.system("open {0}".format(var.GetSummary()))
The file /private/tmp/some string here does not exist.
256
except of course your var has to hold the path to a real file...
If you want to learn more about the lldb Python API's the API docs are here:
https://lldb.llvm.org/python_api.html
and a general tutorial for using Python in lldb is here:
https://lldb.llvm.org/use/python-reference.html
And more information on variable formatting is here:
https://lldb.llvm.org/use/variable.html
I'm writing a small utility for myself that needs to be able to check if a file is a symlink or not.
Using FileType::is_symlink on Windows always returns false (goes for both symlinks to directories, and regular files).
Using regular Rust 2018 edition, is there any way to check if a file is a symlink on Windows?
In my searching, I came across: FileTypeExt - however this requires that you use unstable Rust, as far as I can tell.
Using File::metadata() or fs::metadata() to get the file type will always return false for FileType::is_symlink() because the link has already been followed at that point. The docs note that:
The underlying Metadata struct needs to be retrieved with the fs::symlink_metadata function and not the fs::metadata function. The fs::metadata function follows symbolic links, so is_symlink would always return false for the target file.
use std::fs;
fn main() -> std::io::Result<()> {
let metadata = fs::symlink_metadata("foo.txt")?;
let file_type = metadata.file_type();
let _ = file_type.is_symlink();
Ok(())
}
I am trying to identify when a file is PNG or JPG to apply it as a wallpaper. I am using the SHGetFileInfo to get the type name with the .szTypeName variable, but I just realized that it changes if the OS is in another language.
This is my code:
SHFILEINFOW fileInfo;
UINT sizeFile = sizeof(fileInfo);
UINT Flags = SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES;
// Getting file info to find out if it has JPG or PNG format
SHGetFileInfoW(argv[1], 0, &fileInfo, sizeFile, Flags);
This is how I am validating:
if (wcscmp(fileInfo.szTypeName, L"JPG File") == 0)
{
//Code here
}
When the OS is in spanish, the value changes to "Archivo JPG" so I would have to validate against all language, and does not make sense.
Any idea what other function I can use?
This API is meant to be used to produce a user-facing string representation for known file types1). It is not meant to be used to implement code logic.
More importantly, it doesn't try to parse the file contents. It works off of the file extension alone. If you rename an Excel workbook MySpreadsheet.xlsx to MySpreadsheet.png, it will happily report, that this is a "PNG File".
The solution to your problem is simple: You don't have to do anything, other than filtering on the file extension. Use PathFindExtension (or PathCchFindExtension for Windows 8 and above) to get the file extension from a fully qualified path name.
This can fail, in case the user appended the wrong file extension. Arguably, this isn't something your application should fix, though.
As an aside, you pass SHGFI_USEFILEATTRIBUTES to SHGetFileInfoW but decided to not pass any file attributes (second argument) to the call. This is a bug. See What does SHGFI_USEFILEATTRIBUTES mean? for details.
1) It is the moral equivalent of SHGFI_DISPLAYNAME. The only thing you can do with display names is display them.
My problem is the same as the one mentioned in this answer. I've been trying to understand the code and this is what I learned:
It is failing in the file parse_xml.cgi, tries to get messages (return $message{$name}) from a file named messages (located in the html_en directory).
The $messages value comes from the method GetMessageHash in file adminprotocol-lib.pl:
sub GetMessageHash
{
return $ENV{"QTSSADMINSERVER_EN_MESSAGEHASH"}
}
The $ENV{"QTSSADMINSERVER_EN_MESSAGEHASH"} is set in the file streamingadminserver.pl:
$ENV{"QTSSADMINSERVER_EN_MESSAGEHASH"} = $messages{"en"}
I dont know anything about Perl so I have no idea of what the problem can be, for what I saw $messages{"en"} has the correct value (if I do print($messages{"en"}{'SunStr'} I get the value "Sun")).
However, if I try to do print($ENV{"QTSSADMINSERVER_EN_MESSAGEHASH"}{'SunStr'} I get nothing. Seems like $ENV{"QTSSADMINSERVER_EN_MESSAGEHASH"} is not set
I tried this simple example and it worked fine:
$ENV{"HELLO"} = "hello";
print($ENV{"HELLO"});
and it works fine, prints "hello".
Any idea of what the problem can be?
Looks like $messages{"en"} is a HashRef: A pointer to some memory address holding a key-value-store. You could even print the associated memory address:
perl -le 'my $hashref = {}; print $hashref;'
HASH(0x1548e78)
0x1548e78 is the address, but it's only valid within the same running process. Re-run the sample command and you'll get different addresses each time.
HASH(0x1548e78) is also just a human-readable representation of the real stored value. Setting $hashref2="HASH(0x1548e78)"; won't create a real reference, just a copy of the human-readable string.
You could easily proof this theory using print $ENV{"QTSSADMINSERVER_EN_MESSAGEHASH"} in both script.
Data::Dumper is typically used to show the contents of the referenced hash (memory location):
use Data::Dumper;
print Dumper($messages{"en"});
# or
print Dumper($ENV{"QTSSADMINSERVER_EN_MESSAGEHASH"});
This will also show if the pointer/reference could be dereferenced in both scripts.
The solution for your problem is probably passing the value instead of the HashRef:
$ENV{"QTSSADMINSERVER_EN_SUN"} = $messages{"en"}->{SunStr};
Best Practice is using a -> between both keys. The " or ' quotes for the key also optional if the key is a plain word.
But passing everything through environment variables feels wrong. They might not be able to hold references on OSX (I don't know). You might want to extract the string storage to a include file and load it via require.
See http://www.perlmaven.com/ or http://learn.perl.org for more about Perl.
fix code:
$$ENV{"QTSSADMINSERVER_EN_MESSAGEHASH"} = $messages{"en"};
sub GetMessageHash
{
return $$ENV{"QTSSADMINSERVER_EN_MESSAGEHASH"};
}
ref:
https://github.com/guangbin79/dss6.0.3-linux-patch
What's the way to get default volume on Mac 64-bit?
I have a code like that:
GetVolParmsInfoBuffer buf_64 = { 0 };
status = FSGetVolumeParms(vol_ref, // use default volume
&buf_64, // write
req_count);
The problem is that I can't pass 0 in vol_ref. On Mac 32-bit I could write:
GetVolParmsInfoBuffer buf_32 = { 0 };
HParamBlockRec pb;
pb.ioParam.ioCompletion = NULL; // not doing async I/O
pb.ioParam.ioNamePtr = NULL; // we don't use path name
pb.ioParam.ioVRefNum = 0; // use default volume
pb.ioParam.ioBuffer = reinterpret_cast(&buf_32); // write data here
pb.ioParam.ioReqCount = req_count;
OSErr err = PBHGetVolParmsSync(&pb);
ASSERT_EQ(err, noErr);
Thanks in advance,
- Oleksii
In the File Manager docs, you'll notice a function group titled “Manipulating the Default Volume”. All of those functions are deprecated.
If you search Google for the functions therein, particularly HSetVol, you'll find this mailing list post by Eric Schlegel, which says HSetVol had the effect of setting the current working directory (expressed as a volume/directory pair) on Mac OS. He also says that it doesn't work on Mac OS X: It should work on File Manager functions, but does not set the working directory used for resolving relative paths in other APIs (e.g., open and fopen) like it did on Mac OS.
Moreover, those functions are not available in 64-bit Mac OS X. So the answer is: You don't, because there is no default volume.
The old meaning of it was analogous to the current working directory, so you can do the same thing by getting the CWD and resolving that path to an FSRef. However, for a Mac OS X application (particularly one that doesn't set the CWD by any means, as most don't), this is not terribly useful: The default CWD for an application is /, the root directory of the boot volume. On the other hand, if you run your executable directly or under Xcode's Debugger, its CWD will not be /, which means it could be some other volume—most probably, the one with your Home folder on it.
You should refer to the boot volume (or whatever volume you're interested in) specifically, not attempt to get or simulate getting the default (current working) directory.
For the boot volume, you might try kOnSystemDisk, which is one of the constants in the Folder Manager. If that doesn't work, use Folder Manager's FSFindFolder function to retrieve the System folder, then use File Manager's FSGetVolumeInfo function to get what volume it's on.
Well. I don't really know what "default volume" is. All I know is that Carbon manual (File Manager) says:
ioVRefNum
A volume reference number, 0 for the default volume, or a drive number.
Well, I seem to find the answer for my question.
FSVolumeInfoParam vol_info = { 0 };
vol_info.ioVRefNum = kFSInvalidVolumeRefNum; // will obtain it
vol_info.volumeIndex = 1; // XXX: is it the default volume as well?
vol_info.whichInfo = kFSVolInfoNone; // don't pass volume info
err = PBGetVolumeInfoSync(&vol_info);
The only thing I'm not sure of is if the 1st volume is the default one...
P.S. I guess the problem is that I don't quite understand what "default volume" really is ;-)